VCV Prototype

I feel dumb for not bringing up Julia in my original post. Used to work with that at UCLA when it was v0.2 and completely forgot about it. (In fact, I’m going to rewrite Rack in Julia now :stuck_out_tongue: ).

If we support Julia and Faust, I believe we’d cover more than enough ground for prototypers. And maybe throw in Javascript with duktape which would probably take 30 minutes once we have the abstractions in place.

Anyway, can we decide on a language-agnostic plugin API?

process(inputs[8], knobs[8], buttons[8], outputs[8], lights[8])
processBlock(N, inputs[8][N], knobs[8], buttons[8], outputs[8][N], lights[8])

On API:

Wouldn’t you definitely want an init method in the API and probably a stream/restore handler also into the data block? I could easily imagine these prototypes wanting their own persistent state of some form.

I know when I’m in a plugin I use rack::INFO() a quite often and see messages in a log; a method for foreign language to add a log entry could be super useful either to standard logging or perhaps to an in-module console? I think there’s some other debugging tools you may want in the wild but I’m not sure what they are yet.

Initialization can be done at execute time of the script, at root scope, if the language supports that. Printing can be done with the stdlib of the language, such as console.log() for JS.

Julia! That’s a cool language. I went to one of the JuliaCons back in the day (~0.6 IIRC) and wasn’t sure where it was going to end up, but it looks pretty healthy. It would be a great complement to Faust.

At least one DSP package seems to be in active development.

Picking two powerful but pretty obscure languages makes JS a nice third option; for all its famous flaws, it would be pretty friendly for more stateful/sequency stuff, and it’s definitely better known than Lua.


API: that seems right; my only thought is that it might be worth dropping the hardware metaphor (so knobs => cvoltages (or something) and buttons => gates. IDK what you were imagining for a panel; I was thinking there might be:

  • 8 ins
  • 8 CV ins summed with 8 knobs, and some sort of clipping (plus maybe attenuverters if space permits)
  • 8 gate ins OR’d with 8 physical buttons (latching/momentary combo?)
  • 8 outs
  • 8 output lights

So if it’s control_ins + knobs and gates || buttons then using just knobs and buttons might be slightly confusing.

I think we can also evaluate this advantageous system for developers and open projects
Free Wolfram Engine for developers

@modlfo do you have any more news about it?

This is also news for me. I have been on vacations for a while and I don’t work in the wolfram engine team (I’m in the simulation engine). I think the new version of Wolfram Language will have a compiler, that would make it suitable for real-time DSP. I’m gonna take a look at it once the features are shipped.

@Vortico Julia seem like a good option. It also seems easy for me to add Julia as a new target of the Vult language.

Yeah, I suppose we’ll have to wait on the panel design before getting the exact API down.

I’m not interested in including it since it’s not open-source, but someone could embed it themselves if they want.

I had this in mind with the jsfx plugin,v which used reapers scripting language, but I could never get a decent Windows build for it.

I put out a prototyping module collection for 0.6 a while ago that uses javascript. though I’m intimately familiar with v8 (I’m the maintainer of one of the big v8 embedders), I chose DuckTape to embed due to its lighter build requirements.

it works, it isn’t “fast” (neither is v8 when crossing the c++/javascript membrane too often), but it does allow for some very rapid prototyping.

1 Like

Added “Plan” section to original post.

Very interested. So far I have struck out getting pdlib to build under msys2. Help with this would be welcome. +1 for pdlib and also for csound.

I don’t think a fixed panel with 8 knobs etc. would be a good idea. I would like to have at least the ability to load custom SVG files and instantiate my own user elements like knobs, sliders etc.

Looks like OSC with Faust has some kind of GUI elements. Instead of using OSC, this could be mapped to the VCV Rack controls. E.g. this Faust mixer (works only in Chrome) :

https://faust.grame.fr/tools/editor/?code=https://faust.grame.fr/doc/manual/img/src/exfaust136/exfaust136.dsp

would create and layout the GUI elements automatically, using VCV Rack controls like BefacoSlidePot. Bonus if it integrates a GUI editor to manually layout to fit a SVG design.

But the declarative style of Faust might be difficult for casual users that are not programmers. In my experience Lua is easy to use for programmer newbies. Once I used it to write games on the Playstation Portable, and it was quite popular, many users tried to write their first games with it:

http://www.luaplayer.org/gallery/index.html

A general script interface to the OpenGL canvas would be useful as well. Then someone could implement even things like a scope with it. But would be nice to provide some high-level API on top of it, but this can be implemented in the scripting languages itself, so that you can just call drawLine etc., as I did for my Lua Player:

http://web.archive.org/web/20060207034125/http://wiki.ps2dev.org/psp:lua_player:tutorial

Instead of Image.load, there could be some init-function which loads a SVG file and is called from the constructor of the module. But loading PNG or JPG files might be interesting, too, for some fast prototyping. And then forward all events like onAdd and onReset to the scripting environment.

I think the goal should be to allow to implement any module with a script, which is possible with C++. It would be just a little bit slower, and it would have no segmentation faults :slightly_smiling_face: and you wouldn’t need to design a panel for it.

1 Like

Specifying knobs/ports/buttons/lights dynamically is beyond what most prototypers want to do. I also want to discourage people from “publishing” their prototypes as finalized works. The idea is to be able to share patches which include their code so others can try, but offer a gateway drug for creating actual plugins. That’s why it will be called VCV Prototype. If many people started publishing “polished” modules with scripting languages, their modules, and therefore people’s average experience with Rack would:

  • be 2-200x slower than C++, depending on the scripting language
  • be 20-60MB per published module. With one VCV Prototype plugin, the weight of all scripting languages + LLVM is a one-time cost.
  • The API they used would not have as much support as the full C++ API.
  • They would not get access to custom C++ widgets, which are difficult enough in C++ to keep stable yet functional.

OpenGL is also way beyond what prototypers want to do. Unless you design a separate ShaderToy-like module that reads GLSL. I’d be happy to include this in the VCV Prototype plugin but maybe next year.

5 Likes

Hi @frank–welcome to the Rack forum! :slight_smile:

Agree with @Vortico that the prototyping function should be pretty different than plugin development and that C++ should remain the sole first-class language for actual Rack modules. Per that point, my alpha version of Faust integration reads the Faust GUI elements but only uses that to configure and bound CV inputs to the Faust kernel. The GUI is still up to the programmer (or fixed by the prototype plug).

It would definitely be possible to write a Faust transpiler that took the Faust GUI and set it up in Rack with the full Faust GUI complement, but, speaking for myself, I’m going to put my (unfortunately) limited time towards the prototype side first…

@modlfo wrote that LuaJIT is 15% slower than C++, so not 2-200x. I think this would be acceptable. I guess even 2x slower would be fine for most users. But power users with big patches could see a warning or some marker, that it is a scripted module.

Why do you think it is 20-60 MB per published module? The scripting engine could be included in the core framework. LuaJIT is less than one MB, and then maybe add another MB for the framework. Then the modules would be even smaller than when writing it in C++, and a plugin developer don’t have to install any development environment, which could be difficult depending on the OS. Just instantiate the scripting module, then specify the script file, or even allow to inline it in the VCV file. Security shouldn’t be a problem with Lua. But a user could get a warning when opening a VCV file with an embedded script and asked, if the script should be executed.

The API could have as much support as the full C++ API, there is no general limitation. I didn’t write it would be easy to implement it.

I agree that OpenGL is way to complicated and overkill for most users. But I think that a nice and small high-level API for quick prototyping graphical aspects would be appreciated by most plugin developers, even if they later use C++ to implement the “real” module. Really something simple, like load a SVG file, draw some lines and filled rectangles etc. Or maybe don’t reinvent the wheel and use something like Cairo: http://seriot.ch/pycairo/

Sure, you can embed a scripting language into your own plugin, but this is a different topic than VCV Prototype. I’m not interested in supporting a full non-C++ API.

I think it is necessary for useful prototyping to allow the user to create the UI elements with the script, because then the prototype would be exactly like the final module, when implemented later in C++. I understand that it would be a lot of work to implement and maintain in the VCV Rack code itself, so I guess it is up to module developers like me to do it in a module :slightly_smiling_face: I just did a quick hack to use LuaJIT to create inputs and outputs, and to process audio:


The compiled plugin is 216 kB (stripped). I used LuaJIT as a shared library. Might be better to link it as a static library, but I tried it and there was some error messages with fPIC etc., at which point I gave up to try this. But with the shared library it works. Link to the source code, including the echo script example, and compile instructions are in the video description. Tested for Linux only at the moment, but it should work on the other platforms as well, I didn’t use anything Linux special.
Would be nice to create the inputs and outputs without restarting Rack, but I’m not sure if this is possible. For example the config-call in the constructor of the module is supposed to be called only once. My hack to workaround this is to use a fixed max number of inputs and outputs, but would be better if this would be dynamic and controlled by the script.
3 Likes

another “hack” for configParam() would be to configure them with a set value, and do math to make those conform - set to 0-10 for instance, and if the prototype wants to set them -1' -1’ then simply do the math in the module before passing the value to the interpreter.

You’re free to use scripting languages for creating plugins, but this discussion is off-topic for this thread.