[NOTE: This was originally called Cherry modules, etc. but it was pointed out that there’s another virtual modular synth maker with the same name, so I have now renamed things - it was originally actually going to be Cherry&Son, as a reminder to spend more time with the sprog as well, but this is also something I’ve used now and again!]
Took the plunge this week and decided to learn how to create a module. I’m not a C++ dev, or a designer, so not the most auspicious starting point, but I managed to get something working which is technically a “first module”! It’s incredibly simplistic - just a fixed voltage source with an additive input (useful now and again) but I wanted to get a feel for both the API and working with SVG (not something I’ve done much of either).
I rebuilt the ports and knobs (partly as an exercise, tidying up the SVG code helped me get a feel for how things worked) and also worked out how to use my CAD system of choice to spit out SVG elements when needed (giving me a lot more design accuracy/capability should I ever need it!)
Anyway, the workflow could do with some improvement, but I’ve known worse. I’m a little bit tempted to experiment with “backend logic in rust” for a module I’ve got in mind, just to see how/if that could work - writing the complex logic I’ve got in mind would certainly be nicer in a language with a more expressive type system, but that’s another personal itch.
Anyway, the very trivial module is pictured below, with the intent to develop a distinct dark/minimal style over time.
(Oh, edited to note - next other thing I want to try is experimenting with lighting as I’ve not yet worked out if an RGB LED exists anywhere at the moment, and ideas call for colour-cycling/phasing lights for some things!)
I agree writing modules in rust could be compelling, but beware that doing so would make the path into the rack library quite hard verging on maybe impossible if you plan on your modules using the open source route into the library. Making a nightly people direct download could be pretty doable if that’s your thing,
I think there already are some modules that do fixed voltage with adding another voltage, some also do much more. We also have stacked cables on input to add voltages in an easy way.
But if you personally need this module, then go for it.
What kind of module do you have in mind? Soemthing fresh? Something new? Something incredible? I’m just curious
A quick update - after a bit more reading and some help from folks on Discord, I worked out that sticking to px sizing makes life much easier, and while experimenting with that, started work on a new set of components (ports, knobs, etc.) to form a consistent style. Still hopefully “in keeping” with the built-in components, but with a slightly darker, rubberier feel… Quite happy with how that’s turning out, the updated look is below…
Yeah, I use a bit of software called Rhino 3D, it’s actually a pretty powerful modelling and engineering tool, but it’s as good at 2D as it as at 3D, and I know it well from using it in other areas. It’s very much overkill in a sense, and I still end up using Inkscape just to bring things together and tidy up the SVGs, but it makes it very easy to stick to grids/known angles/fillet dimensions and so on.
Oh I’m 100% sure that this module does nothing new whatsoever, it’s purely a testbed for getting a workflow sorted, playing around with graphics, smoothing out any build problems, and so on. This is definitely not of any actual value yet!
The actual modules I’m interested in creating are a bit more complex - generally around complex sequencing and performing, where there’s a lot of logic and “domain model” to express, and where something like Rust might be more expressive to write that. My intent at the moment is effectively to only call from CPP to Rust (never the other way around) and effectively have a single function which does something like “current states → new states” where states might be input voltages and switch positions as input, and output voltages and lighting/display values as output. That way the process function is effectively “gather state, call Rust logic, update new state”. Whether that will work at all well… I’ll see, I guess! If I can get it working at all, I know Rust and the build system well, CPP much less so.
use the event-handling provided by the VCV Rack API
re-use all the code from the API, as there is DSP-Code and a lot of other stuff that could be helpful when developing a sequencer (maybe a clock, a MIDI-parser, a slew-limiter, a trigger-generator, simd-handling - there’s really a lot well tested code ready to use that can save you lots and lots of hours developing and testing/debugging)
Other things that need to be handled are:
initializing/resetting the module logic
loading/saving data-structures to/from json
constructing and managing user-defined GUI-elements, because not everything can be done with the given elements of buttons, knobs, sliders, and so on - maybe you will need custum display-elements or user-input-elements, maybe you will need custom context-menu-entries, maybe you will need custom key-bindings, e.g. for copy/paste actions inside your sequencer, I don’t know
My advice is to study the VCV Rack API carefully (not only the API-doc but also the source-code itself).
Yes these are all very fair points, although the event-handling could probably still form a bridge I think. In terms of DSP code, I actually have Rust-equivalents of almost everything in that sense, but we’ll see where we end up. It may well be more effort than it’s worth to mix the two worlds. I have been reading most of the Rack code in general to get a feel for it!
Still continuing onwards, and learning a lot as I go! Have now started work on a first “real” module, although it’s very much inspired in logic by an existing real-world module (with a few extra tweaks). It’s about 50% there, still plenty to do on both panel and code, but it’s beginning to work reasonably well. All of the actual module logic aside from panel configuration and layout is in Rust as well, which seems to be working quite nicely. I’ve access to params, ports, lights, from within the Rust code with effectively no overhead (just wrapped up shared pointers to the same memory and same type layouts), and it all seems fine so far!