VCV Prototype: Share your prototypes

I was looking for a good idea to try out the prototype module. So I made the Morphing Triangle Oscillator that Finetales suggested

I’m no DSP programmer. I’m barely a programmer. So it’s all a little hackey. Especially the S&H. But it can actually get pretty sonically interesting. I haven’t made any real modules yet, but this one will probably get ported if I do.

Knob & In 1: V/Octave
Knob & In 2: Skew
Knob & In 3: S&H
Knob & In 4: Diet
In 5: Hard Sync
In 6: FM
{
  "id": 69,
  "plugin": "VCV-Prototype",
  "version": "1.2.0",
  "model": "Prototype",
  "data": {
    "path": "/Users/nateallen/Documents/Rack/plugins-v1/VCV-Prototype/examples/trimorph.js",
    "script": "// Morphing Triangle Oscillator\n// Designed by u/Finetales\n// Programmed by Nate Allen\n\n// Code modified from the Voltage-controlled oscillator example by Andrew Belt\n\n\n// Knob & In 1: V/Octave\n// Knob & In 2: Skew\n// Knob & In 3: S&H\n// Knob & In 4: Diet\n// In 5: Hard Sync\n// In 6: FM\n\nconfig.frameDivider = 1\nconfig.bufferSize = 16\n\nlet phase = 0\n\n// SKEW CONSTANTS\n// The max slope when skewing peaks left and right.\n// We never technically get to a true sawtooth, but we can get close\nconst maxSlope = 50\n\n\n// STEP CONSTANTS\n// When the step knob is at zero, this is ignored.\n// This sets the maximum phase steps when you do turn the knob\nconst maxPrecision = 100\n// This set the exponential ramp through the step settings\nconst exp = 10\n// Since we apply the step knob exponentially,\n// there's a point where we don't actually get a cycling\n// waveform anymore. There's a single sample through the whole\n// cycle. This calculates that point, and we'll not let our values\n// go past that.\nconst maxAmount = 1-(Math.pow(1/maxPrecision, 1/exp))\n\n// DIET CONSTANTS\n// Set the max exponent for the diet\nconst maxCurve = 8\n\n// Used to tell whether our sync oscillator has crossed the zero point\nlet syncPositive = false\n\nfunction process(block) {\n\t// Knob ranges from -5 to 5 octaves\n\tlet pitch = block.knobs[0] * 10 - 5\n\t// Input follows 1V/oct standard\n\t// Take the first input's first buffer value\n\tpitch += block.inputs[0][0]\n\n\tlet skew = block.knobs[1]\n\tskew += block.inputs[1][0] / 10\n\t// skew\n\tlet slope = Math.pow(maxSlope, skew * 2 - 1) + 1\n\tlet pairedSlope = 1 / (slope-1) + 1\n\n\tlet step = block.knobs[2]\n\tstep += block.inputs[2][0] / 10\n\n\tlet diet = block.knobs[3]\n\tdiet += block.inputs[3][0] / 10\n\tlet curve = Math.pow(maxCurve, diet * 2 - 1)\n\n\tif(syncPositive && block.inputs[4][0] < 0) {\n\t\tsyncPositive = false\n\t}\n\n\tif(!syncPositive && block.inputs[4][0] > 0) {\n\t\tsyncPositive = true\n\t\tphase = 0\n\t}\n\n\t// The relationship between 1V/oct pitch and frequency is `freq = 2^pitch`.\n\t// Default frequency is middle C (C4) in Hz.\n\t// https://vcvrack.com/manual/VoltageStandards.html#pitch-and-frequencies\n\tlet freq = 261.6256 * Math.pow(2, pitch)\n\tdisplay(\"Freq: \" + freq.toFixed(3) + \" Hz / Skew:\"\n\t\t+ skew + \" / Step: \" + step + \" / diet: \" + diet)\n\n\t// Set all samples in output buffer\n\tlet deltaPhase = config.frameDivider * block.sampleTime * freq\n\tfor (let i = 0; i < block.bufferSize; i++) {\n\t\t// Accumulate phase\n\t\tphase += deltaPhase\n\t\t// Wrap phase around range [0, 1]\n\t\tphase %= 1\n\n\t\tlet y = sampleAndHold(phase, step)\n\n\t\t// Basic FM\n\t\ty += block.inputs[5][0] / 10 + 0.5\n\t\ty %= 1\n\n\t\ty *= slope\n\n\t\tif (y > 1)\n\t\t\ty = pairedSlope * (slope - y) / slope\n\n\t\t// waveshaper based on diet\n\t\ty = Math.pow(y, curve)\n\n\t\tblock.outputs[0][i] = y * 10 - 5\n\t}\n}\n\nfunction sampleAndHold(phase, amount){\n\tif(amount <= 0)\n\t\treturn phase\n\tamount *= maxAmount\n\tprecision = maxPrecision * Math.pow(1-amount, exp)\n\treturn Math.round(phase * precision) / precision\n}\n"
  }
}

Edit - So, I realized that this is just Tides, aka Audible Instruments tidal modulator 2. So, this was fun to build, but you get all of this functionality from that module, and it’s much less CPU intensive since it’s not a prototype.

7 Likes