midi-cv-buddy

midiCvBuddy · sources

Hardware 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.

Turns a hardware MIDI keyboard or controller into the pitch + gate + velocity CV the rest of the rack speaks — the classic MIDI-to-CV interface. It is MONOPHONIC: when you hold a chord it picks one winning note (by the card's voice-priority setting — last-played, lowest, or highest) and tracks that. Mental model: play a key and PITCH follows it as 1V/octave, GATE goes high while you hold and dips briefly on a retrigger so envelopes re-fire, and VELOCITY latches how hard you struck. Pitch-bend is summed into the pitch output. The card owns the device dropdown, channel filter, voice-priority and retrigger choices (all discrete, saved in the patch — no audio-side knobs); Web MIDI permission is requested only when you click Connect, not on patch load. For polyphony, use MIDI LANE's poly output instead; this module is the simple mono workhorse.

the faceplate

midi-cv-buddypitch_cvcvgategatevelocity_cvcvaudiocvgatepitch
0 inputs · 3 outputs · 0 params

outputs

idcablewhat it does
pitch_cvcvThe 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)
gategateStays 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; gate — acts while the level is high (reacts to both edges)
velocity_cvcvHow 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)

controls

controlwhat it does
Midi cv buddy channel {n}Which MIDI channel this module listens to — ALL, or one of the sixteen. The channels are shown 1..16 the way every keyboard and sequencer prints them on its own front panel, while the wire format underneath is 0..15. Pick a channel when more than one instrument is sending on the same cable and you want this one to hear only its own track; leave it on ALL for a single keyboard, where a filter can only ever make the module silent. Changing it clears any held keys first, because a note-off arriving on the OLD channel would otherwise be dropped and strand the gate high forever.
Midi cv buddy connect {n}The one-time-per-origin permission gesture. Web MIDI needs the browser's consent before any device is even visible, and until it is granted this module has no stream to listen to and all three jacks sit at rest — so this is the first thing to press, not an optional extra. It reaches the same request every MIDI module in the rack shares, which always yields a nameable outcome: granted, refused, unsupported, or the quiet case where the browser suppressed its own prompt without telling anyone. Once access is granted the dock's device body lists the inputs it found and remembers the one you pick, so a reloaded patch re-attaches without another click.
Midi cv buddy priority {n}Which held key wins when you are holding more than one, because this module drives a single PITCH and GATE pair and has to choose. LAST follows the most recently pressed note, which is what a keyboard player expects and what almost every software synth does. LOW pins the lowest note, the classic mono-bass behaviour — hold a root and play a melody above it and the bass never moves. HIGH pins the highest, which does the same for a lead line under a held pedal tone. Changing it re-picks the winner immediately but does NOT re-fire the gate, so a settings change never sounds like a new note.
Midi cv buddy retrig {n}Whether a fresh key press re-fires downstream envelopes while you are already holding a note. ON drops the gate to 0 for exactly one audio block before re-raising it, which an ADSR or a VCA reads as a new note and re-attacks; that is the percussive, every-note-articulated feel. OFF leaves the gate high through the change, so the pitch moves and the envelope keeps whatever it was doing — legato, and the only way to get a real slide out of a mono line. It applies from the next note-on; the currently sounding note is untouched.

source

midi-cv-buddy.ts on GitHub.

Generated from packages/web/src/lib/{audio,video}/module-registry.ts · repo