# Rack development blog

Someone brought up a point of confusion of how the rules of polyphonic modules are defined, so I’d like to clarify the motivation behind the polyphony standard.

If a monophonic signal is patched into a polyphonic module currently running with N engines (each representing a polyphonic channel), the monophonic signal is copied to all engines.

If you’re familiar with programming, you can think of monophonic signals as “scalars” that implicitly cast to polyphonic signals (vectors) when incompatible types interact. For example, the expression a + [b1, b2, b3] should reduce to [a + b1, a + b2, a + b3].

If you’re familiar with mathematics, a monophonic signal is a rank-0 tensor (over time) while a polyphonic signal is a rank-1 tensor (over time). An operation like summing would look like (a + \vec{b})_i := a + b_i. (Note that in this analogy, rank-1 tensors with dimension 1 cannot be represented in Rack.)

The user-benefiting motivation is to be able to use the same input port (e.g. FM input) rather than two different ports (e.g. mono FM and poly FM inputs) in order to either modulate each polyphonic engine (e.g. VCO) with a same-channel polyphonic signal or to modulate all polyphonic engines with a 1-channel monophonic signal.

The standard says

The number of active engines N should be defined by the number of channels of the “primary” input

However, it is purposefully vague in specifying what a “primary” input is. In some cases, there is no primary input at all because all inputs must be treated with equal respect. Martin Lueders and I discussed that when polyphon-izing Befaco A*B+C (where neither A, B, nor C are the “primary” input), the number of engines should be computed by max(#A, #B, #C) where #x is the number of channels of input x. This allows you to mix-and-match mono and poly cables in the A, B, and C inputs, so the result is a polyphonic signal that correctly controls the rest of your polyphonic patch.

Just some thoughts if you’re developing a module that supports polyphony.

6 Likes

A few plugin developers have asked me about the difficulty of preparing your plugin for Rack v2. Will we have another Rack v0.6 -> v1 transition that requires minutes to hours of porting? No. The goal for the Rack v2 API is for at least 90% of plugins to require zero changes to code. Developers of closed-source plugins will need to send me builds of their plugins before the Rack v2 launch. The Rack v2 SDK will be released at least two weeks before Rack v2.

Of course, to take advantage of new features such as Port labels, you’ll need to add code.

4 Likes

Proposal for adding many new Module events.

1 Like

Rack v2 is being worked on, but it’ll be a while before I get around to publishing the source code.

Coming in Rack v2: Port tooltips with voltage readings of all polyphonic channels.

19 Likes

Coming in Rack v2: There is no more “engine thread”. The engine can only be stepped (i.e. advanced in time) by other threads, such as the audio driver thread managed by VCV Audio or the encoder thread in VCV Recorder. This restructuring has a number of massive benefits.

• Support for multiple audio drivers. You can use your laptop’s headphone jack, your USB audio interface, Expert Sleepers Eurorack audio interface, etc. all at the same time. No more crashes or deadlocks. Of course, only one audio driver can “drive” the engine clock rate. Other audio drivers might drop samples if their clock rates don’t match exactly. This is selectable by enabling “Primary audio module” in the module’s context menu.

• In order for each audio buffer to be delivered to your audio device, the audio thread no longer has to lock itself (telling the OS to put it to sleep), wait on the engine thread, and unlock itself (waiting for the OS to schedule the thread again). This saves 1-10 microseconds per audio buffer on average, but more importantly, it saves 100-1000 microseconds when the CPU has an unusually high workload, which could result in audio glitches.
• The new “Host” audio driver used in Rack for DAWs will run all module code (in Module::process()) directly in the “DAW thread”. Locking the DAW thread to wait on another thread is somewhat unacceptable.
• Modules like VCV Recorder that can run much faster than real-time can render minutes of audio in only seconds, if they are chosen as the “Primary audio module”.
• Stability (i.e. probability of crashing) is improved, simply because there are fewer threads dancing around complicated mutexes/shared data.
• The “Real-time priority” menu item is removed, since the thread priority is now managed elsewhere (RtAudio, etc.)
33 Likes

Proposal for a module whitelist:

By the way, after I approve a proposal, potential changes will typically not be reconsidered until the next Rack major version. So if you have objections or alternative proposals, get them in now before you miss the boat.

7 Likes

Various minor features for Rack 2.0:

• Red clip lights on VCV Audio when signal goes beyond ±10V.

• Add module bypass routing API, which replaces module disabling, so developers can specify direct routes from inputs to outputs when users “bypass” the module.

• Add infinity and NaN protection to cables, so they won’t propagate non-finite values from badly behaving modules. (Performance not fully tested, could be removed.)

• Duplicating modules also duplicates their input cables.

void appendAudioMenu(ui::Menu* menu, audio::Port* port);


so plugin developers can develop custom audio/MIDI interfaces without adding an AudioWidget/MidiWidget to their panel like VCV Audio-8, MIDI-CV, etc.

• Full support for numpad keys, such as Enter to open the Module Browser and Ctrl-0/Minus/Plus for zooming the rack.

• Evaluate mathematical expressions in parameter context menu fields.

• And most importantly , use MenuSeparator instead of MenuEntry for separating menu items.

45 Likes

Recent features and fixes in Rack v2:

• Add basic headless support with the -h flag. It simply loads the given patch or autosave without a window.

• Add multiple knob modes: scaled linear, absolute rotary, and relative rotary.

• Add “knobLinearSensitivity” property to settings.

• Add timestamps to MIDI messages, and use them in Core MIDI modules to improve timing and drastically reduce clock jitter.

• Allow SysEx messages through MIDI drivers.

26 Likes

This is the first public screenshot of VCV Rack for DAWs, specifically VCV Rack for VST2 Linux. Not pictured, the sine output of VCV VCO-1 is patched into VCV Audio-8, which is using the new “Host” audio/MIDI driver that communicates with the DAW instead of your sound card. VST parameters (soon including labels, units, and actual values) control the parameters of Rack modules. Audio is as stable as can be, since there is no thread-switching overhead as with Rack v1.

The actual VST2 plugin is a ~100KB binary, which dynamically links to a lib-ized version of Rack. This allows for many plugin variations, such as effect/instrument, 2/8/16-channel, and potential VST3/AU/AAX/LV2 plugins, without having N copies of the entire Rack binary.

The source code is maintained in a private git branch and is rebased for every new v2 commit. This means that features and bug fixes added to Rack v2 will immediately be available for Rack for DAWs, so they will follow the same version numbers and will usually be released same-day.

After testing on the other OS’s and DAWs, I’ll focus on windowing, graphics, and improving mouse/keyboard interaction.

54 Likes

Added “MPE mode” to MIDI-CC and MIDI-Gate in Rack v2 which generates 16-voice signals with CC values and gates. Along with MIDI-CV, which already supports MPE in Rack v1, this allows you to take advantage of all features with polyphony on MPE-enabled devices, such as the LinnStrument, ROLI Seaboard, Haken Continuum, Eigenharp, Soundplane, and others.

24 Likes

Added SwitchQuantity to Rack v2. Instead of displaying 0, 1, 2, etc for switches, this displays the actual value names instead.

Usage example:

configSwitch(MODE_PARAM, 0, 1, 1, "Engine mode", {"Digital", "Analog"});

23 Likes

In Rack v2, VCV MIDI-CC now supports 14-bit CC commands (i.e. MSB on CC 0-31, LSB on CC 32-63). The Gamepad MIDI driver now generates 14-bit CC commands.

25 Likes
• Added VCV Audio-2 module which I expect will become the “default” audio interface module in most users’ patches since stereo in/out is usually all that is needed.

• Made UI tweaks to more closely follow Grayscale’s design. The above screenshot demonstrates all these changes. This includes removing the LED glow/halo effect, brightening up the PJ301M port graphic, and toning down drop shadows.

• Added fix suggested by @stoermelder to allow plugins to register their own audio/MIDI drivers. For example, it will be possible to create a plugin that installs an audio driver that communicates with an Arduino over a serial connection and exposes CV as a 1000 Hz audio interface. You will then be able to select the “My Custom Arduino Protocol” driver in VCV Audio, and it will handle resampling as needed. Or, register a MIDI device that converts MIDI CC messages to/from your custom Arduino protocol. I’m sure there are many ideas the plugin developer community can invent with this API.

• Finished “library-izing” Rack. To run the standalone GPLv3 version of Rack, you will launch a small wrapper executable (~100KB) which only contains a main() function that initializes/destroys the Rack application state. The rest of the code is in libRack.so/dylib/dll. Rack for DAWs will come with VST2 plugin binaries (and possibly VST3/AU/AAX later) that link to this library as well. You could theoretically embed this library into your own application and use only the parts you need, such as the plugin loader and engine. However, I have not yet tested this use case in depth so it will not be supported in Rack v2.0.

• Low-fidelity sample rates will be officially supported and offered in the UI, so plugin developers need to add support for these if their code makes assumptions about possible sample rates.

36 Likes
• Rack v2 has switched from using key codes to key names, which correctly handle all keyboard layouts such as AZERTY or Dvorak. Plugin developers should use e.keyName == "q" instead of e.key == GLFW_KEY_Q for checking printable keys. Non-printable keys should still use e.key, e.g. e.key == GLFW_KEY_ESCAPE. More information in the docstrings when Rack v2 source code is released.

• Overhauled Rack engine threading model. Now all Engine methods are thread-safe and can safely be called from anywhere, with a few additional rules specified in the docstrings. Performance of threading is improved, and after all bugs are fixed with public testing, engine stability will be increased (decreased thread-related crashes).

• Removed engine pausing. This feature no longer makes sense after the recent engine restructure that allows modules to be processed on the audio thread.

24 Likes
• Allow disabling smoothing for MIDI-CV (pitch and mod wheel), MIDI-CC, and MIDI-Map.

• Add several module presets for many Core modules.

• API

• Add Engine::getNumModules() and Engine::getModuleIds() to query the Engine’s modules.
• Module presets beginning with “1_”, “42_”, “001_”, etc do not display those numbers. This allows you to manually order module presets. (Remember to use leading zeros as needed so alphanumeric sorting gives the correct order.)
9 Likes

Added Mouse device to “Computer keyboard/mouse” MIDI driver. This converts your mouse cursor position to MIDI CC 0 and 1 to be used with VCV MIDI-CC. Supports 14-bit MSB/LSB MIDI CC.

28 Likes

The tentative release plan for Rack v2 and Rack for DAWs is the following. By “wait”, I mean “ensure that a certain amount of time passes before the next step”.

• Continue working on Rack v2 and Rack for DAWs.
• Once both are “alpha” quality, release Rack v2 source code.
• Wait at least 4 weeks while testers and plugin developers review the code.
• Once both are “beta” quality, begin providing development builds of Rack v2. Send Rack for DAWs builds and licenses to testers.
• Wait at least 2 weeks for users to review the development builds.
• Once Rack v2 is “stable” quality, release it.
• Wait at least 2 weeks.
• Once marketing is ready, release Rack for DAWs.

The following people will be granted beta builds and licenses of Rack for DAWs at no charge.

• Developers of open-source and commercial plugins on the VCV Library.
• Developers of freeware plugins at my discretion.
• A few artists who have tested commercial plugins for VCV in the past.
65 Likes

I am requesting plugin developer feedback for this proposal.

4 Likes

Rack v2 has a new .vcv patch format, which is a compressed folder containing the JSON-serialized patch.json file and other files, such as module patch assets. Read more:

Other changes:

• Add module whitelist to Module Browser which synchronizes individual modules chosen in the VCV Library.
• Re-render framebuffers when subpixel offset changes, fixing bug that makes ports and knobs appear slightly offset at certain zoom levels.
• API
• Add several convenient filesystem routines to system::.
• Move all string:: functions dealing with filesystem paths to system::.
23 Likes

This is my (extremely) tentative feature wishlist for Rack v3.

The theme of Rack v3 is “massive performance improvements through architectural overhauls”.

• Migrate to C++17, or at the least C++14, if most developers’ Apple clang versions support it. (Apple is usually 5 years behind C++ versions.) This will probably end support for Mac 10.7.
• Compile with AVX. Add simd::float_8 etc.
• Consider switching from nanovg to Skia or vkvg or Intel fastuidraw or something else. A nanovg API wrapper will be needed.
• Use better algorithms and heuristics for stepping modules, such as possibly:
• Store buffers in cables and step modules in sections, as allowed by the cable graph.
• Add Module::processBuffer().

#### Recent Rack v2 changelog:

• Use randomly-generated 53-bit IDs to identify modules and cables in the patch.

#### Forum tip:

To respond to any of these blog posts, click on the grey timestamp in the top-right of the post and click “New Topic”

21 Likes