Very basic question from absolute beginner


New user here :wink:

So I have just got the very basics of module building going and have my very first module that just applies the setting of a “Gain” knob to the input and sets this at the output (so the very most basic attenuator). The process() function in this is easy as it’s just getVoltage, multiply, setVoltage.

Thankfully that all works though I did have an issue using as the SVG must have the same name as the Slug. If you use “createmodule foo res/bar.svg …” then the svg::load() is for foo.svg not bar.svg - but I guess this is quickly obvious when no background loads!

Anyway I’m now considering a simple oscillator. So, while I haven’t seen it written down anywhere, I get that if the sample rate is set to 44.1kHz then process() is going to get called 44,100 times per second.

So say you want to play international A at 440Hz as a sine you need to fit 440 cycles of that into one second so you will have 100 calls to process() for each cycle (well roughly, actually 44,100 / 440) so you have to map that to a 0 to 360 (or rather -pi to +pi) range. So does that mean you’ll always need to use args.sampleTime in your calculation of where in the wave you are? I guess the problem I’m having getting my brain around this is exactly how do you map the the value from args to an input you pass to sine?

Or say you are programming a sawtooth. I believe the output voltage range is bipolar in the range -5V to +5V (or is it 0V … 10V?) so would you, in this example be ramping from one limit (0 or -5) to the other (10 or +5) over those same 100 steps?

Or perhaps easier - is there a SIMPLE example anywhere that shows this kind of stuff (preferably well commented code! ;-). In vcvrack/libraries/repos I’ve followed the links through to a number of module collections and have looked at source but on the whole these are not written as simple examples but as industrial grade, highly optimised, highly reusable code that actually makes it quite tricky to track down the core logic.

PS I have found the odd YouTube about writing modules but while Vult looks excellent in the long run it kind of obscures the fundamentals when starting out. Are there other examples?

Oh and if there really is some documentation that explains things like how often process() is called I’d love to know the location as I can’t help thinking I’m not looking in the right place and I’m failing to get the whole story :wink:

I believe that the example process method in the tutorial is for a simple oscillator. Let me just check.

Yes, process is called at the sample rate. You can either read the sample rate (or its inverse the sample time) in you process method, or you can read it at startup, and override the onSampleRateChanged (I might have the wrong name there) method to be informed when it changes.

Hi and welcome to the forum.

There is this video by Klirrfactor, maybe you found it already?

This might well be useful:

1 Like

LOL - I was going to post that! Yeah, I think those are good because they are just the basics, no fancy stuff.

1 Like

Wow, great replies and the Squinky Labs stuff especially looks like EXACTLY the clear examples I was looking for. Thanks so much!

I shall inwardly digest those examples and see what I can come up with.

I already have a toe in the water of synthesizer development but so far everything I’ve done ( First real demo of my synth - YouTube ) has been using actual hardware (Teensy 4 @ 600MHz with I2S DAC) and most of that is “handed to you on a plate” with the most excellent Teensy Audio library which already has all the basic elements like oscillators and filters.

System diagram

But I actually wanted to use VCV Rack as a kind of “prototyping” system to try out ideas of how I could make something more “modular” using Teensy.

One big difference with Teensy is that it calls processing with buffers rather than per-sample so that is quite a change in the way one thinks about operation and is probably the real source of my confusion.

This all looks like it could be a lot of fun !! :crazy_face:

PS do you know, I’m a complete idiot! I must have read PluginDevelopmentTutorial about 10 times but I was more concerned about createplugin and createmodule (at first I even missed the fact that they were different and failed to see how they relate) also the fact that my SVG was not appearing (because of the SVG load of wrong name) distracted me too, that I completely failed to take in the section about “DSP kernel” - it actually answers the doubts I had about when process() is called, how args.sampleTime might be used and everything really - must learn to pay more attention!! :confused: