My First Plugin - Meander

I am working on my first VCV Rack plugin module- Meander. This is an attempt to duplicate a Windows app that I developed over the years and that I use in my music performances. For examples from over the years, see Stream CyberPunKen music | Listen to songs, albums, playlists for free on SoundCloud . This VCV module is once again primarily for my own use, but depending on how it works out, I will release to open source eventually, and assuming interest.

Attached is a screen clip of my module in Rack, in its very crude development phase, trying to get the panel layout frozen before I start adapting Meander source code to Rack. As you can see, Meander is an 80HP module at present with approximately 80 params, including buttons. My question here is what might I expect in terms of CPU load with this many parameters and quite extensive source code? Also, how often (in milliseconds) is process() called per module, and is there a limit on how long the code can run before experiencing problems? Most of the code is setup related, such as defining scales and keys and circle of 5ths harmonic progression steps and patterns. But, there is a significant ammount of code associated per process() call to determine the harmony,. melody, arp, and bass notes to play.

Lastly, in Meander for Windows (and for Max/MSP), I create an event queue which I populate “off beat” so that I have the notes figured out before they are needed. Then on the beats I process the event queue and play any notes that are due, based on system time. Has anyone created an event queue in a Rack module?

Thanks, Ken

5 Likes

I’m answering this based on my own experience writing modules, which may or may not be directly applicable to you, but I’ll try to answer what I can and am happy to expand if needed.

just iterating through parameters and doing simple math, not too much CPU usage - the number of parameters itself doesn’t make too much of a difference, it’s the complexity of the code/math underneath that matters. if you’re doing a lot of math, it makes sense to look into using the float_4 type, even if you’re not doing parallel processing: having everything aligned helps a lot, plus you can use the SSE math functions that have been exported to gain quite a bit efficiency.

once for every sample, so if the user is running at a sample rate of 44100, the 44100 times per second, or 1.0 / 44100. that varies with the sample rate set. you don’t need to do anything on every call, just respond, so you have the option of buffering and processing every 10th call, let’s say. just understand that doing that could add latency that the user could see.

you can fire off a new thread and do your processing there, and communicate with that thread for processing, just remember that unless you’re using a lock-free queue, you’ll likely spin-lock while waiting for the thread lock of your data.

1 Like

The really crucial thing Jerry mentions is that you don’t have to do everything on every process call. So don’t look at all those knobs every call. Think very carefully about how often then need to be serviced and only do that. As Jerry said, merely having a control does not add any (significant?) CPU as long as you don’t look at it and do something expensive with the value.

1 Like

or, even if you do look at it, only do the math if something has changed. there are a lot of filter examples on the internet that do a calculation every time a value is set, which would make you think that you need to set the values every loop, but why? that’s likely expensive math!

That’s good to know and in line with my thinking. Probably the most math intensive thing I do is to calculate 1-D Fractal Brownian Motion (fBm) float (or double) random numbers in range (0.0-1.0) via a PRNG. These are used to calculate a scaled array index and then the actual values (scale notes, etc) are determined by indexed array lookup. All if the arrays are created and populated at startup. I do not do any DSP calculations in Meander.

fBm is so much more interesting for music purposes that using a uniform distribution. In essence, Meander applies a variable low pass two point filter to smooth the fBm more or less as desired, particularly for determine melody notes to play.

Yeah, I think there’s a little bit of “philosophy” or personal preference there. I tend to do all the math every time, just not every sample. I think it’s just habit, but it does have the advantage that your normal case is also the worst case, so it’s easy to know if you are “efficient enough”. If you to the math only on value changes, you sort of should test/consider what happens if you CV control all those things at the same time - is the performance still “ok”? Of course either is preferable to doing nothing. The AS mixer does 8 sin() and 8 cos() calls every process call for the pan knobs. That’s why it was so easy to make it 20x faster.