Rack v1 development blog

Is there a plugin example of how to create context menu entries with v1?

1 Like

Core MIDI-CV has a lot of menu items.

1 Like

Doh. Didn’t even think to look in Core. Thanks!

I’m beginning to add polyphony to Fundamental modules. I wanted to try the new simd library on a polyphony application, and it works better than expected. Fundamental VCA-2 has a 3x speedup when processing 16 polyphonic channels with SSE vs serially. The code is nearly as readable as a serial version (https://github.com/VCVRack/Fundamental/blob/v1/src/VCA.cpp#L37-L91) with the main differences being

  • You have to f32_4::load() and v.store() to convert from a float* to f32_4 vector and vise-versa.
  • You can’t branch with if. You can instead use masking, e.g.
// Wrap on the interval [-0.5, 0.5)
phase -= (phase >= 0.5f) & 1.f;

(Although note that phase -= trunc(phase); is probably faster for wrapping on the interval [0, 1). Just demonstrating this trick.)

  • You must process blocks of 4 floats. I use for (int c = 0; c < channels; c += 4) for this. If you have only 1 channel (or any non-multiple of 4), this will process 4 instead, but at virtually no wasted cost.
  • All functions like sin() or pow() are implemented in simd/functions.hpp, so don’t prefix them with std::.

Once you get the hang of it, writing SIMD code is only slightly more involved than writing your serial reference implementation (which you should do first).

7 Likes

Awesome, beautiful code! Thanks for sharing this, open source is so cool :slight_smile:

2 Likes

Added a helper.py script to the Rack v1 repository for quickly creating new plugins and modules. Here’s an example session.

~/VCV/Rack/plugins ❯ ../helper.py createplugin MyPlugin
Plugin name [MyPlugin]: My Plugin
Version [1.0.0]:
License (if open-source, use license identifier from https://spdx.org/licenses/) [proprietary]: CC0-1.0
Author []: VCV
Author email (optional) []: contact@vcvrack.com
Author website URL (optional) []: https://vcvrack.com/
Plugin website URL (optional) []:
Manual website URL (optional) []:
Source code URL (optional) []:
Donate URL (optional) []:
Manifest created at MyPlugin/plugin.json
Created template plugin in MyPlugin/
Initialized empty Git repository in ~/VCV/Rack/plugins/MyPlugin/.git/
You may use `make`, `make clean`, `make dist`, `make install`, etc in the MyPlugin/ directory.

~/VCV/Rack/plugins ❯ cd MyPlugin

~/VCV/Rack/plugins/MyPlugin ❯ ls
Makefile  plugin.json  res  src

~/VCV/Rack/plugins/MyPlugin ❯ mv ../MyModule.svg res/

~/VCV/Rack/plugins/MyPlugin ❯ ../../helper.py createmodule MyModule
Module name [MyModule]: My Module
One-line description (optional) []:
Tags (comma-separated, see https://github.com/VCVRack/Rack/blob/v1/src/plugin.cpp#L543 for list) []: vco, polyphonic
Added MyModule to plugin.json
Components extracted from res/MyModule.svg
Source file generated at src/MyModule.cpp

~/VCV/Rack/plugins/MyPlugin ❯ make
g++  -Wsuggest-override -std=c++11  -fPIC -I../../include -I../../dep/include -MMD -MP -g -O3 -march=nocona -funsafe-math-optimizations -Wall -Wextra -Wno-unused-parameter -DARCH_LIN -c -o build/src/plugin.cpp.o src/plugin.cpp
g++  -Wsuggest-override -std=c++11  -fPIC -I../../include -I../../dep/include -MMD -MP -g -O3 -march=nocona -funsafe-math-optimizations -Wall -Wextra -Wno-unused-parameter -DARCH_LIN -c -o build/src/MyModule.cpp.o src/MyModule.cpp
g++ -o plugin.so build/src/plugin.cpp.o build/src/MyModule.cpp.o  -shared

~/VCV/Rack/plugins/MyPlugin ❯ ls
build  Makefile  plugin.json  plugin.so  res  src

Instructions for creating panels are shown by running helper.py createmodule. Here’s a copy.

Instructions for creating a panel:

Note: This information is probably out of date. See https://vcvrack.com/manual/Panel.html

  • Only Inkscape is supported by this script and Rack’s SVG renderer.
  • Create a document with units in “mm”, height of 128.5 mm, and width of a multiple of 5.08 mm (1 HP in Eurorack).
  • Design the panel.
  • Create a layer named “widgets”.
  • For each component, create a shape on the widgets layer.
    • Use a circle to place a component by its center.
      The size of the circle does not matter, only the center point.
      A create*Centered() call is generated in C++.
    • Use a rectangle to to place a component by its top-left point.
      This should only be used when the shape’s size is equal to the component’s size in C++.
      A create*() call is generated in C++.
  • Set the color of each shape depending on the component’s type.
    • Param: red #ff0000
    • Input: green #00ff00
    • Output: blue #0000ff
    • Light: magenta #ff00ff
    • Custom widgets: yellow #ffff00
  • Hide the widgets layer and save to res/<module slug>.svg.
7 Likes

A few of the specifics in this surprise me. I expect that

for (int c = 0; c < channels; c += 4) { v[c / 4] = ...

would produce worse code than

for (unsigned c = 0; c < channels; c += 4) { v[c >> 2] = ...

but I’d have to disassemble to be sure. Also, line 72 uses std::pow() while line 81 uses pow() ?

I’d be surprised if those don’t generate the same code. The vector pow has the signature f32_4 pow(f32_4, f32_4) and is in the simd namespace. If you want to use them both without namespaces, add using std::pow; in your function. This is useful when writing generic functions and classes.

I believe they can if -ffast-math is used. I think there is one more aggressive than fast math, it’s name escapes me right now.

I did some (unrelated to Rack) tests and when no optimization flags are in place, GCC would just call out to the standard library. Even if told that it was OK to generate AVX code it would still do so. Although once fast math is turned on, it will use the native math opcodes instead of the C functions (and then once it was willing to do that it was further willing to vectorize them.)

-ffast-math has no effect on integers, at least in your two “for” loops example.

A post was split to a new topic: UI text is blurry

Events of the form event::MouseButton) have been renamed to MouseButtonEvent, etc. If you’ve started porting your code to the v1 API, you can rename them with

perl -pi -e 's/event::(\w+)/$1Event/g' src/*

Dev builds:
https://vcvrack.com/downloads/Rack-1.dev.3eb0426-lin.zip
https://vcvrack.com/downloads/Rack-1.dev.3eb0426-mac.dmg
https://vcvrack.com/downloads/Rack-1.dev.3eb0426-win.zip
Make sure your Rack user directory is backed up and removed before running dev builds.

Post bug reports on https://github.com/VCVRack/Rack/issues

4 Likes

Dependencies have been updated. As always, to make sure your dependencies are up to date, run

git submodule sync
git submodule update
cd dep
make -j8

To really make sure, run make clean before make, which will rebuild all dependencies (15-60 minutes).

Thanks for the info Andrew.
What about the status of Fundamental plugins about polyphony?

The following plugins still need cleanup, optimization, and polyphony:
- VCO
- VCO2
- VCF
- LFO
- LFO2
- Delay
- ADSR
- Unity
- Scope
- SEQ3

1 Like

Just out of curiosity how is polyphony going to work with Scope? One cable in and 16(?) channels of waves?

N blue (or pink) lines will be drawn.

1 Like

Added https://vcvrack.com/manual/PanelTutorial.html to the manual.

8 Likes

Make sure there is enough space between knobs and ports to put your thumbs between them.

= breath of fresh air, thanks Andrew!

1 Like