K

Be a modulation source

Turn your device into an LFO that wiggles other devices.

A device can output movement: a signal that drives other devices' controls, like an LFO. Give it a modulation output and write a value each sample.

m.addPort(modulationOut("Mod"));

A slow sine LFO. Keep a phase and a sample rate on the device, advance the phase each sample:

class Node extends Device {
  private phase: f32 = 0;
  private sr: f32 = 48000;

  describe(): Manifest {
    const m = new Manifest("LFO");
    m.addParam(new ParamDef("rate", "Rate", "Rate", 0.1, 20.0, 2.0, false));
    m.addPort(modulationOut("Mod"));
    return m;
  }

  prepare(sampleRate: f64, maxBlock: i32): void {
    this.sr = <f32>sampleRate;
  }

  process(ctx: Ctx): void {
    const inc = ctx.param(0) / this.sr; // Rate, in Hz
    const tau = <f32>(2.0 * Math.PI);
    for (let i = 0; i < ctx.n; i++) {
      ctx.modOut(i, Mathf.sin(this.phase * tau));
      this.phase += inc;
      if (this.phase >= <f32>1.0) this.phase -= <f32>1.0;
    }
  }
}

How deep it goes and which controls it hits are set where the modulation output is plugged in. Don't want to hand-roll the shape? The building blocks include RandomLfo and friends.

Several outputs from one device

A device can declare up to 8 modulation outputs: call modulationOut(...) once per output. The first port keeps the bare modulation-out handle and is written with ctx.modOut(i, value); every further port gets an indexed handle (modulation-out-1, modulation-out-2, ...) and is written with ctx.modOutAt(out, i, value), where out is the port's declaration order (0 is the first port). Each output shows as its own handle on the tile, labeled when there is more than one, so a random sequencer can drive pitch, gate, and velocity targets from independent streams:

describe(): Manifest {
  const m = new Manifest("TripleMod");
  m.addPort(modulationOut("Pitch"));
  m.addPort(modulationOut("Gate"));
  m.addPort(modulationOut("Velocity"));
  return m;
}

process(ctx: Ctx): void {
  for (let i = 0; i < ctx.n; i++) {
    ctx.modOut(i, this.pitch);          // output 0 (same as modOutAt(0, ...))
    ctx.modOutAt(1, i, this.gate);
    ctx.modOutAt(2, i, this.velocity);
  }
}