Showcase: Eight-channel generative groovebox on Zynthian, played entirely from a Maschine MK2

Hi all,
I have been quiet here for a while because I was busy turning a Zynthian into
something I can play without looking at a screen. It works now, so here it is.

Repo: GitHub - Witzman/Generative-Techno-ZynthianMaschine-MKII: Eight-channel generative groovebox: Zynthian on a Raspberry Pi 4, played from a Maschine MK2 · GitHub

Build guide: Generative-Techno ZynthianMaschine MKII — an eight-channel generative groovebox

Video (no hands — see below): https://youtu.be/VJs85sTF880

What it is
A Raspberry Pi 4 running ZynthianOS Oram-2601-1, a Native Instruments
Maschine MK2 over USB, and nothing else. No audio interface - every measurement
in the project was made on the Pi’s own headphone jack at 48 kHz.
Eight channels, always alive: five euclidean drum channels and three
Turing-machine voices. Nothing is created or torn down while you play, so
there is no chain-building mid-set and no dropout when you change your mind. A
channel can switch between drum and voice behaviour without swapping its
engine.
You do not draw patterns. You set hits, rotation and randomness, and the
generator writes the notes.

The part that matters for Zynthian people
It writes into zynseq, not into a sequencer of its own.
That was the single most important design decision and it is what makes the
thing feel like part of Zynthian rather than a thing bolted onto it:

  • patterns persist in ordinary Zynthian snapshots
  • the touchscreen pattern editor mirrors exactly what the pads show, live
  • banks are scenes, saved in the snapshot, and a set lands on the bank it was
    saved on

the whole instrument is a ctrldev driver plus a HID daemon.
No fork of zynthian-ui. Upstream files that must change are patched by a script inside
my repo, not edited in place
The Maschine daemon descends from William Light’s maschine.rs via my earlier
MaschineMK2\_linux. It talks to the driver over OSC on loopback, and it is
what paints the pad LEDs and both displays.

The generative side
The three voices are Turing machines - a shift register clocked once per pass,
mutated one bit at a time, read as pitch. Set MELODY to 0 and the loop freezes
bit-identically for as long as you leave it. A voice can run a bounded random
walk instead, which strolls where the register jumps, and one voice can be fed
another’s register so the two drift toward each other without ever converging. A
slow chord walker moves the root all three share, along the scale rather than
chromatically, so three independent lines become a progression.
The drums evolve too: RHYTHM lets steps appear and disappear bar to bar, and
tapping a pad writes into that same register rather than editing the pattern -
a tap takes a step away where there is one and puts one in where there is not.
So a hand-chosen rhythm survives ROTATE, and HITS or LENGTH put the plain
euclidean line back.

Pads are pressure-sensitive: squeeze a held pad on a voice and the filter opens
for as long as you press. And because the driver counts bars, a gesture can land
on a boundary instead of under your finger - ARM composes a macro with a length
(a drop, thinner odds, half or double time, a break, a ratchet ramp), it fires on
the bar and resolves by itself. A bar-synced LFO can be bound to any timbre knob.
SHIFT + REC captures the master to a WAV on the Pi.

The honest part
Two things I would rather say here than have someone find:

  1. A modulated LV2 plugin hosted with a GUI burns about 70–75% of a core doing
    nothing. I measured this last week on silence. It is not the DSP - the audio
    threads are identical with and without the modulator, and 99.9% of the cost is
    userspace in jalv.gtk3, charged per parameter write, not a latched loop. The only fix that costs nothing musically is hosting those plugins without a GUI, and I have not worked out yet whether Zynthian can be told to do that per-instance. If anyone here knows, I would very much like to hear it - that is half of why I am posting.
  2. Nothing here is proved by a document. This project has a rule that a spec,
    a status file or a sentence I wrote an hour ago is a claim, not evidence - because
    I shipped three predicted numbers once, straight into a manifest, a test and
    three guide pages, and all three were wrong. So: the test suites (driver, daemon,
    tools, system files, installer dry-runs) all run with no Pi and no controller
    attached, twelve AST guards read the driver’s source to answer questions no
    running instance can, and the installer suite shadows ssh, scp and
    systemctl with stubs that fail if called - so a dry run that actually executes
    something breaks my build instead of someone’s rig.

The video is scripted: the run was generated, then the panel you see is that same
run played back, so the pads, both displays and every lamp are what the hardware
actually showed. I would rather say that than have you assume I have four hands.

3 Likes

Far out.

1 Like

Nice work!

You can disable all LV2 native GUIs by disabling VNC. If there is a particular plugin that causes an issue, report it via the issue tracker and we can flag it to not use it’s GUI. We do this for a few plugins. Some work better with QT which we can also flag in the code.

2 Likes

As a non native english speaker, i could read this in two ways.

  • Far out from what i have seen last time - nice.
  • Far out, from whats this communities focus is.

I hope it was the second reading :slight_smile:

Until 8h ago, i wasnt even aware, that plugins would show own UIs in a VNC session at all. I was only using a raspi touchscreen nd never saw anything, giving me a hin, there is even more.
This morning i added a step to my installer, deactivating the VNC Process for Instrument GUIs - this helped to settle the performance issue for now.
As you are stil able to map the paramenters via the gestures on the controller, there is (and never was, because i did not know it existed) no use of diplayind the plugins GUI.

1 Like

Far out = Wow.

1 Like

Glad you learned something. Every day is a school day. :wink:

Will you please tell me what LV2 was causing the high CPU usage? We should avoid this. It does not happen on most LV2 so I expect you found one that behaves poorly.

1 Like

It wasn’t a badly-behaved plugin, and I don’t think it’s really my project either - I’d call most of it a default worth revisiting.

Two separate costs, both from the same place: config_remote_display() hosts every GUI-carrying plugin in jalv.gtk3 whenever vncserver1 is active, globally, whether or not anyone ever opens a GUI.

The idle cost, which needs no unusual usage at all. Same snapshot, 19 instances, transport stopped, the only change being the host: 189% → 98% of a core.
A non-modulated padthv1 went 11.7% → 3.8% on its own. That’s just what GUI-hosting costs on a Pi 4, and every headless rig with VNC on is paying it.

The write cost, which is where my instrument made it loud. If anything writes parameters to one of those instances a few times a second - a modulator, an LFO, a MIDI-learned CC sweep - the GTK idle loop goes to ~80% of a core. Roughly 140 ms of CPU per write.
It’s not the DSP: the modulated instance’s audio thread matched its unmodulated siblings exactly (10.0% each), the whole difference was in the main thread, 99.9% userspace. Stop the writes, it drops to sibling level instantly; resume, it comes straight back.
Denormals were the obvious suspect and were refuted. Plugins with no UI cost nothing however hard
you write to them.

The one I caught was Dragonfly Room Reverb, but only because it was the modulation target - I’d faced the same for 4 other GUI-carrying plugins while testing, so naming one to avoid would be the wrong lesson.

Workaround for me:
ZYNTHIAN_VNCSERVER_ENABLED=0 puts everything in plain jalv.
Worth knowing that only vncserver1 (:6081) takes part in the host choice, so vncserver0 (:6080, the Zynthian UI) can stay up and you needn’t lose your screen - that split isn’t obvious, since one envar drives both. Stopping the service by hand doesn’t hold either: default_vncserver() re-reads the envar at every start and pulls it back via novnc1’s Requires=.

1 Like

So it would be much better to have a second screen on HDMI or DSI and use the GFX hardware for rendering, instead of mangling everything through VNC overhead.

The cost is not the drawing and not the VNC link. In every one of those runs
nobody was connected and no window was open anywhere - and it still burned the
core.

What it actually costs is one thing: whenever my modulator nudges a
parameter, the GUI-capable host does a lot of work behind the scenes, whether
anyone is looking or not. Freeze the modulators and the cost vanishes; release
them and it comes straight back.

A second screen wouldn’t change that, because Zynthian never puts plugin
windows on a real screen at all - they only exist on the hidden VNC desktop.
Moving them to HDMI would mean changing where the window appears, not what is
being paid for.

Where you’re right: for actually using a plugin’s own interface, a real
screen would beat VNC when it comes to comfort.
It just wouldn’t give back the CPU that is currently being wasted.

But i am not using the Instruments GUIs at all, as i can controll the parameters direcly via maschines Encoders.

2 Likes

Having the VNC enabled makes the native GUI to run and render in the internal VNC framebuffer. The VNC + native GUIs will cause almost the same CPU overload not matter if someone is connected or not remotely. We strongly recommend to disable VNC (native GUIs!) for live performance. If you do intensive use of modulation, this recommendation becomes almost imperative.

This is not something is going to change in the near future. Using a second display instead of VNC probably wont improve things too much. There are hard limits we can’t circumvent. Plugin’s native GUIs are CPU hungry and RBPi CPU resources are limited compared to conventional computers. Most native GUI’s won’t take advantage of GPU acceleration. Perhaps some of them will do, but not most of them.

Regards,

2 Likes

Totally fine for me, my workarround disabling the GUI VNC is currently fine for me. I just wanted to share my findings.

This is a well troden road of discussion and we do have some ideas simmering deep within our minds on how to manage other displays but at the moment we are focused on getting the next stable release out. The element here that suprised me is that you had VNC enabled at all. By default it is disabled and must be manually enabled. So it is odd that you have to do something to disable it.