diff --git a/examples/vco.js b/examples/vco.js index f5184dc..99f5721 100644 --- a/examples/vco.js +++ b/examples/vco.js @@ -1,7 +1,7 @@ // Voltage-controlled oscillator example // by Andrew Belt -// JavaScript isn't ideal for audio generating and processing due to it being 10-100 less efficient than C++, but it's still an easy way to learn simple DSP. +// For audio synthesis and process, JavaScript is 10-100x less efficient than C++, but it's still an easy way to learn to program DSP. config.frameDivider = 1 config.bufferSize = 16 @@ -11,6 +11,7 @@ function process(block) { // Knob ranges from -5 to 5 octaves let pitch = block.knobs[0] * 10 - 5 // Input follows 1V/oct standard + // Take the first input's first buffer value pitch += block.inputs[0][0] // The relationship between 1V/oct pitch and frequency is `freq = 2^pitch`. diff --git a/examples/vco.lua b/examples/vco.lua new file mode 100644 index 0000000..5a274f6 --- /dev/null +++ b/examples/vco.lua @@ -0,0 +1,34 @@ +-- Voltage-controlled oscillator example +-- by Andrew Belt + +-- For audio synthesis and process, Lua is 10-100x less efficient than C++, but it's still an easy way to learn to program DSP. + +config.frameDivider = 1 +config.bufferSize = 16 + +phase = 0 +function process(block) + -- Knob ranges from -5 to 5 octaves + pitch = block.knobs[1] * 10 - 5 + -- Input follows 1V/oct standard + -- Take the first input's first buffer value + pitch = pitch + block.inputs[1][1] + + -- The relationship between 1V/oct pitch and frequency is `freq = 2^pitch`. + -- Default frequency is middle C (C4) in Hz. + -- https://vcvrack.com/manual/VoltageStandards.html#pitch-and-frequencies + freq = 261.6256 * math.pow(2, pitch) + display("Freq: " .. string.format("%.3f", freq) .. " Hz") + + -- Set all samples in output buffer + deltaPhase = config.frameDivider * block.sampleTime * freq + for i=1,block.bufferSize do + -- Accumulate phase + phase = phase + deltaPhase + -- Wrap phase around range [0, 1] + phase = phase % 1 + + -- Convert phase to sine output + block.outputs[1][i] = math.sin(2 * math.pi * phase) * 5 + end +end \ No newline at end of file