midi-cv-buddy
midiCvBuddy · sources · schema v1Hardware MIDI controller → pitch + gate + velocity CV. Uses the browser's built-in Web MIDI API (no third-party library) and converts incoming note-on / note-off / pitch-bend messages into three ConstantSourceNode outputs: pitch_cv (V/oct, 0V = C4 = MIDI 60, with pitch-bend summed in at the MIDI-standard ±2 semitones), gate (0/1), and velocity_cv (0..1). Monophonic with three voice-priority modes (LAST = newest key wins, the conventional default; LOW = lowest key, classic mono-bass behavior; HIGH = highest), a RETRIG toggle that drops the gate to 0 for one audio block between successive note-ons (so a downstream ADSR re-fires) versus legato (gate stays high through key changes), an ALL/1..16 channel filter, and a device-picker dropdown that hot-plugs when controllers connect/disconnect. The user clicks "Connect MIDI…" once per origin to grant permission; subsequent reloads reuse the grant. End-to-end latency is honest about the Web MIDI main-thread path (~5-10 ms typical on Chrome/macOS); event.timeStamp is mapped to ctx.currentTime + a 2 ms lookahead so scheduling lands at the start of the next audio block rather than mid-block.
the faceplate
outputs
| id | cable | what it does |
|---|---|---|
pitch_cv | cv | The current note as pitch CV in volts-per-octave (the codebase convention 0V = C4 = MIDI note 60), with pitch-bend summed in (default ±2 semitones). It tracks the winning held key per the card's voice-priority mode and latches the last note after you let go, so a downstream VCO holds its pitch through the gate's fall rather than snapping to a default. control voltage (CV) |
gate | gate | Stays high while at least one key is held and low when all keys are released. On a retrigger (a fresh strike while the retrigger mode wants a re-fire) it briefly dips to 0 for one audio block before re-rising, so an ADSR or VCA downstream re-fires its envelope cleanly. Patch it into an envelope's gate or a VCA. gate / trigger |
velocity_cv | cv | How hard the most recent note was struck, as 0..1 CV (MIDI velocity 0..127 scaled by 1/127). It updates on each note-on and latches between events, so you can route it to a VCA level or a filter cutoff for velocity-sensitive dynamics. control voltage (CV) |
source
midi-cv-buddy.ts on GitHub.