Introducing miRack – an optimised fork of VCVRack for Raspberry Pi and others

April 20, 2018

Lately I got distracted from Dwarf Fortress Remote development by discovering VCVRack - an open-source virtual Eurorack-style modular synthesizer written by Andrew Belt. I don't even remember how it happened, also I'm not really a musician but I have a soft spot for toying with music apps (and developing ones as you know - SoundGrid, SoundGrid Live!). But then I, also accidentally, noticed a discussion related to running it on Raspberry Pi, basically stating that was unusable on such hardware. I could not resist changing that, especially considering that I finally got a reason to buy an RPi.

Important note: in fact, I started development o RPi 3 Model B, but then ended up buying an ASUS Tinker Board instead (because it looks cool). In tests, Tinker Board is about twice faster than Raspberry Pi. However, without active cooling, my board reduces frequency to at most about 1.2-1.4 GHz (from original 1.8 GHz), so it's not that much faster than RPi when I'm running Rack on it. Below when I say RPi I will be referring to all similar single board computers, just take into account that your results may be different from mine.

VCVRack is a wonderful project, and especially the community that formed around it quite quickly with many developers making plugins implementing various modules (the Rack application itself is just a host and doesn't include any modules apart from MIDI and audio in/out). Unfortunately it sucks performanse-wise - the choice of frameworks, the base Rack code itself, the fact that plugins are created by different people with different level of expertise and care for performance - all this causes people to complain about performance even on desktop hardware.

Interestingly, UI part (as opposed to computational part) was the worst and took the most time to get decent FPS on RPi hardware. Rack uses SVG for all UI elements and NanoVG for rendering, and with improper use and without additional optimisations both to NanoVG and Rack, this led to each frame requiring up to a thousand and more (depending on the number of modules added) of OpenGL calls - this is a bad practice and unacceptable even on desktop hardware and just could not work on RPi. I've reduced this number to just several dozens when idle, and another several dozens when adjusting knobs and sliders (not counting frequently updated widgets like scopes that just have to be fully rendered every time).

I did remove some of the visual effects like shadows and light halos - because the performance is more important on weak hardware than visual effects after all. Some of them may be enabled again later (and I definitely need to bring back different colours for cables) when I assess their impact on FPS. Also, I'm planning to add support to work without X server into GLFW (the library used by Rack for OpenGL window creation and mouse/keyboard events). In my tests I noticed significant FPS increase without an X server on my hardware.

Then, I've implemented multi-threading for the actual signal processing. This isn't strictly neccessary on desktop but vital on multi-core hardware with much slower individual cores. Also, I made the engine run only on callback from audio driver - this is probably temporary but I've noticed some performance issues related to thread synchronisation otherwise. I need to see what side effects this change has apart from not being able to route output to a DAW (via VCVRack's Bridge plugin), but that's not important when running on RPi anyway.

And then there were various changes to individual modules - to avoid sample rate conversion, to tweak quality vs performance, to fix rendering, to cache values instead of calculating each step, or to at least not to compute values for module outputs that are not connected.

Of course, this project has limitations when running on RPi and similar hardware, and it obviously depends on the number of modules used in a patch and the modules themselves.

The VCVRack license disallows the use of some of its graphics resources and of the "VCV" name part in derivative works, so now I need to take care of this (and of some occasional crashes) before a public release. My software will be named miRack. Once it's ready, I'll explain in more detail the differences between it and VCVRack, its limitations, and compatibility with existing plugins (in short, plugins are source-compatible). By the way, of course, it can also be used on desktop hardware (at least on Mac and Liux as I haven't tried building on Windows), and UI performance improvements are noticeable.