An openFrameworks addon which makes oscillation and modulation easy
README
ofxModulation
Reusable LFO oscillators and step-sequencer parameter recording for live video performance.
CPU-only and GL-version agnostic. Depends only on
ofMain (+ ofxMidi, which is included so MIDI-binding examples compile; the core classes do not use it).Components
| Class | Purpose |
|---|---|
Oscillator | Phase-accumulator waveform generator. Waves: SINE, TRIANGLE, SAW, SQUARE, NOISE (smooth per-cycle), RANDOM (sample-and-hold). tick(dt) advances an internal phase; valueAt(t) evaluates at an absolute time. |
Lfo | A named oscillator with a modulation depth, a per-LFO scale, string Targets (pass, paramName), and depthBindable/rateBindable flags for MIDI routing. value() = osc depth scale. |
StepSequencer | Multi-channel step recorder/player (the p_lock pattern). setChannelValue() records at the current step; getChannelValue() returns the one-pole-smoothed playback. start() back-fills all steps from current values. |
ModulationEngine | Thin owner: a bank of named LFOs plus one StepSequencer, advanced with one tick(dt) per frame. |
Usage
#include "ofxModulation.h"
ModulationEngine mod;
void ofApp::setup()
{
Lfo *x = mod.createLfo("x");
x->setDepth(0.5f);
x->setScale(0.1f); // parameter coefficient
x->oscillator().setFrequency(0.25f); // cycles/sec
x->oscillator().setWave(Oscillator::TRIANGLE);
mod.setupSequencer(17, 240); // channels, steps
mod.sequencer().setSmoothing(0.5f);
}
void ofApp::update()
{
mod.tick(ofGetLastFrameTime()); // advance all LFOs + one sequencer step
// Apply an LFO additively to a shader param. Reading the base fresh after
// MIDI apply each frame avoids frame-to-frame compounding.
float base = shaders.getParam(0, "uHue");
shaders.setParam(0, "uHue", base + mod.getLfoValue("x"));
}MIDI glue stays in the app: bind a CC to an LFO depth with
midi.bindContinuous(cc, "xDepth") and assign midi.get("xDepth") to lfo->setDepth().License
MIT
ofxAddons