I am a newcomer into VCV rack plugin development, although not a beginner in signal processing. My understanding is that the signal processing by the process function is sample-based, meaning that the incoming signal is processed at the sample rate. Therefore, if one wishes to do [even simple] operations on blocks of data (say, take the average of N=8 samples, within a running window), one needs somehow to store the N samples somewhere/somehow. It is not clear to me how this can be done in the code. Is there anybody around willing to share with me a very simple example on how this can be implemented?
Any help would be highly appreciated. Thanks!
P.S. This topic is mentioned here: Spelunking in the VCV code but there is no explanation about how this is done.
You put them in some simple data structure like a ring buffer. But it’s rare and undesirable to do this in vcv if you don’t have to. You can do filter like you mentioned without block processing, just calculate the data on the fly, one sample at a time.
Some people do buffer data. An fit analyzer like the Bogaudio one is an example. I have seen some modules buffer up 4samples so the could batter utilize SSE instructions. Fwiw I have 25 or 30 modules in the library and have never buffered data. Well, almost never.
If you really have to, you would use a ring buffer to buffer the data. The Rack SDK has dsp::DoubleRingBuffer which you could use.
for this simple operation one can probably just accumulate the samples (i.e. stacking them) and then compute the average. I am not sure how this is done (i.e. storing the, say, sum value at each call of the process functions). But that is a separate issue.
For operations that do not need to retain all the information about the single samples I agree this would do,. However, when the single samples matter (e.g. when you need to do an FFT), I guess buffering is the only way.
Thanks, Xenakios, I will have a look to see whether I find examples where dsp::DoubleRingBuffer is used. I indeed need to do FFTs and I am not concerned about real-time processing, so that buffering and latency is not an issue. Thanks a lot!
Thanks. Indeed, I need to do spectral analysis and FFT is a key ingredient there. So, I guess I am doomed to use buffering.
There’s no way around having to do the buffering if you need to use FFT.
Yeah. VCV Rack API: rack::dsp::DoubleRingBuffer< T, S > Struct Template Reference seems to be what I need. I just have to find some example to start from.
A simple ring buffer that is accessed only from the audio thread (the process() method) is also very trivial to implement yourself. You just need a buffer, its length and a counter as member variables of the Module subclass.
// member variables
int m_bufferCounter = 0;
int m_bufferLength = 4096;
void process(const ProcessArgs& args) override
float insample = inputs[IN_AUDIO].getVoltageSum();
m_buffer[m_bufferCounter] = insample;
if (m_bufferCounter == m_bufferLength)
m_bufferCounter = 0;
// buffer now has enough data to process
However, in many cases you will end up needing multiple ring buffers, so it’s probably a good idea to abstract the ring buffering into a separate class (or use an existing implementation).
for buffering up blocks for fft I might go with a pair of regular old arrays of float. much more important, however, is how you are going to schedule the FFT? If you just do it on the Module::process() call you will put a huge spike into the CPU consumption and cause a pop for many users (assuming the block is fairly large).
What he said!
If the FFT is big, it’s best to use a separate worker thread for that. This is what we did in the MindMeld EQMaster.
Yes, I think many NYSTHI plugins use a worker thread for that, and a couple of mine do. Here’s a link to my (ancient) article on this. SquinkyVCV/efficient-plugins.md at e1fbd48c50ad244bdaba8759cafe4129e8b6dac7 · squinkylabs/SquinkyVCV · GitHub
Matt from Bogaudio also I believe does it.
so all the cool kids do it! And probably a whole bunch of people we don’t know about
Thanks! Very kind of you!
Thanks a lot. I will have a look at you MindMeld EQ Master.
Thanks, Squinky.Labs. I will read your article with great interest.