🔧 ProgrammierungThe Cascade Runs Ahead of the Flip(16.09.2026 um 02:21 Uhr)
🔧 ProgrammierungWeekly Dev Log 2026-W19(16.09.2026 um 02:30 Uhr)
🔧 ProgrammierungI wanted to remember what changed after an AI coding session(16.09.2026 um 02:34 Uhr)
🔧 ProgrammierungYour change process governs code. This was not code.(16.09.2026 um 02:39 Uhr)
🔧 ProgrammierungRadio: A Shared Channel for my AI Agents(16.09.2026 um 02:40 Uhr)
🔧 ProgrammierungThe Cascade Runs Ahead of the Flip(16.09.2026 um 02:21 Uhr)
🔧 ProgrammierungWeekly Dev Log 2026-W19(16.09.2026 um 02:30 Uhr)
🔧 ProgrammierungI wanted to remember what changed after an AI coding session(16.09.2026 um 02:34 Uhr)
🔧 ProgrammierungYour change process governs code. This was not code.(16.09.2026 um 02:39 Uhr)
🔧 ProgrammierungRadio: A Shared Channel for my AI Agents(16.09.2026 um 02:40 Uhr)

🔧 Programmierung 🕛 vor 2 Monaten 7 Min Lesezeit
0

You Don't Need MIDI-OX Anymore: Building a SysEx Librarian with the Web MIDI API

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




You Don't Need MIDI-OX Anymore: Building a SysEx Librarian with the Web MIDI API



If you own a Yamaha DX7 or a Roland Juno-106, you already know the ritual.



Install a utility from 2003. Fight USB-MIDI drivers on Windows 11. Open MIDI-OX. Configure ports. Pray the SysEx buffer doesn't choke mid-dump. Save a .syx file with a name like backup_final_v3_REAL.syx. Lose it anyway.



I built has been in Chromium browsers for years. Almost nobody used it for real librarian workflows until recently. That's the gap.









Architecture in one sentence



Browser ↔ Web MIDI ↔ USB interface ↔ synth. Server stores raw hex + parsed names. Restore streams hex back out the same port.




CODE
┌─────────────┐    requestMIDIAccess({ sysex: true })    ┌──────────────┐
│ Chrome │ ◄──────────────────────────────────────► │ USB-MIDI │
│ knob.monster│ Uint8Array SysEx streams │ interface │
└──────┬──────┘ └──────┬───────┘
│ POST sysex_hex + synth_model │
▼ ▼
┌─────────────┐ ┌──────────────┐
│ Server │ parse_dx7_sysex() / parse_juno106() │ DX7 / Juno │
│ + Postgres │ → ["BASS 1", "BRASS 2", ...] │ / M1 / CZ │
└─────────────┘ └──────────────┘












Step 1: Ask for SysEx permission (not optional)



Default Web MIDI access is useless for librarians. You need sysex: true or the browser strips exclusive messages.




CODE
const midiAccess = await navigator.requestMIDIAccess({ sysex: true });

for (const input of midiAccess.inputs.values()) {
input.onmidimessage = (event) => {
ingestSysExBytes(new Uint8Array(event.data));
};
}






Reality check: Works in Chrome, Edge, and Opera. Safari and Firefox users are out of luck for now. We say that upfront on the landing page. Hiding it creates angry forum posts.









Step 2: Request a dump (every synth is a special snowflake)



There is no universal "please send all patches" command. Each manufacturer has its own handshake.



For a Yamaha DX7, we send a bulk dump request:




CODE
const dumpRequest = new Uint8Array([0xF0, 0x43, 0x20, 0x09, 0xF7]);
outputPort.send(dumpRequest);






Korg M1, Roland Jupiter-6, and Casio CZ-101 each get different byte sequences. The Juno-106 doesn't respond to an outbound request at all: the user must press WRITE on the panel while we're listening. The UI has to say that out loud or support mail explodes.



We concatenate incoming messages into one buffer, watch for idle timeout, then POST the hex string to the server.









Step 3: Reassemble the stream



SysEx often arrives as multiple MIDIMessage events. A single bulk dump can be thousands of bytes.




CODE
let ingestedBytes = [];

function ingestSysExBytes(data) {
for (const byte of data) {
ingestedBytes.push(byte);
}
}

function finalizeDump() {
const hexString = ingestedBytes
.map((b) => b.toString(16).padStart(2, "0"))
.join("");

return fetch("/banks", {
method: "POST",
body: formDataWith(hexString),
});
}






We log the stream in a monospace "MIDI monitor" panel so power users can sanity-check the handshake. Transparency builds trust with synth people who've been burned by black-box tools before.









Step 4: Index extraction (where the magic is)



Raw SysEx is opaque. Users want names: EP BASS, UNI VERS, A11 ACID BASS.






DX7: names live at a fixed offset



A DX7 32-voice bulk dump is ~4104 bytes. Each voice is 128 bytes. The patch name is the last 10 bytes of each voice structure.



Python on the server (same logic you'd use in JS):




CODE
def clean_ascii(name_bytes: bytes) -> str:
chars = []
for b in name_bytes:
if 32 <= b <= 126:
chars.append(chr(b))
else:
chars.append(" ")
return "".join(chars).strip()


def parse_dx7_sysex(data: bytes) -> list[str]:
voices = []
# Find F0 43 .. 09 header or accept raw 4096-byte voice block
start_offset = 6 if data[:4] == b"\xF0\x43\x00\x09" else 0

for i in range(32):
voice_offset = start_offset + (i * 128)
name_offset = voice_offset + 118
name_bytes = data[name_offset : name_offset + 10]
patch_name = clean_ascii(name_bytes) or f"DX7 Voice {i + 1:02d}"
voices.append(patch_name)

return voices






That + 118 line is the entire product demo. Hex editor on the left, readable names on the right.






Juno-106: no stored names, infer from sliders



Juno patches don't ship ASCII labels in the dump. We parse 18 parameter bytes per message and generate descriptors like A11 ACID BASS from cutoff, resonance, and envelope shape. Different problem, same goal: human-readable rows in a table.






Generic fallback: scan for printable ASCII runs



Unknown synth? Walk the byte stream, collect 6–16 character printable sequences, filter junk. Surprisingly effective on 80s ROMs that embed names inline.









Step 5: Single-click recall (flash the payload back)



Backup is half the job. Restore means sending the same bytes back through the output port, often with pacing so 1980s UART buffers don't overflow.




CODE
async function flashBank(sysexHex) {
const bytes = hexToUint8Array(sysexHex);
outputPort.send(bytes); // chunk + delay in production
}






We chunk large transfers and show progress. Users named this "Sync to Synth" in usability tests. Engineers call it "write SysEx." Same thing.









What we deliberately did NOT build





  • A patch editor. No virtual sliders. We're a librarian, not a programmer.


  • A DAW plugin. Browser tab, not VST.


  • Universal synth support on day one. DX7, Juno-106, M1, Jupiter-6, CZ-101, then generic scan. Depth beats breadth.



Saying "no" on the landing page filtered out the wrong customers and reduced support load.









Security and privacy (brief, because people ask)




  • Libraries are private by default

  • We store raw .syx equivalent hex for restore fidelity

  • Parsing extracts names for the UI; we don't need to expose your dumps publicly


  • requestMIDIAccess is a powerful permission. We only ask when you start a capture









Business model (for the curious)



Lifetime pricing, not subscription. Personal tier for bedroom studios, Studio tier for commercial use. Regional pricing (CAD, GBP, EUR) because $39 on a Canadian screen reads American, not "fair."



Organic discovery beat ads at this LTV. HN, Synthtopia, Gearspace, SEO guides for "DX7 backup" and "MIDI-OX alternative Mac." The Web MIDI angle is what developers share. The Juno-106 angle is what musicians search.









Lessons if you're building hardware-facing web apps





  1. Lead with the demo moment. HN taught me: one live counter beats three paragraphs of copy. For us, it's patch names appearing from hex.


  2. Document manufacturer quirks in UI, not a PDF manual from 1987.


  3. Sysex: true or go home.


  4. Ship parsers incrementally. One great DX7 path > ten broken generic paths.


  5. Export guarantee. Let people download .syx anytime. Trust compounds.









If this is you



You're the person with a DX7 in the bedroom and a drawer full of cables that almost work.



You're the Juno owner who finally got SysEx working once, then forgot the switch combo for six months.



You're the repair tech who just needs the bank out before the customer leaves, and back in when the battery's swapped.



You're the developer who looked at MIDI-OX and thought: this should be a URL, not an installer.



You don't need another rabbit hole. You need the dump saved, the names readable, the restore one click away.





  • Vollständiger Original-Artikel
    Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
    ↗ Original-Artikel auf dev.to lesen
    Wie bewertest du diesen Beitrag?
    1 Klick Feedback
    Teilen mit Netzwerk & Team:

    Community-Analysen & Experten-Meinungen 0

    Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
    Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
    Community Pulse: Relevanz-Einschätzung
    1 Klick Experten-Votum
    🔴 Akute Relevanz 0%
    🟡 In Evaluierung 0%
    🟢 Keine Auswirkung 0%
    Spannende Innovation 0%
    Verwandte Story-Cluster & Quellen (Vektor-KI)
    Port 8095 Engine
    1 Quelle
    Building a SOC 2 Evidence Collector: A Small-Team Alternative to Manual Audit Prep
    1 Quelle
    From Ring to Repo: Predicting Developer Fatigue Using Oura Data and Random Forest
    1 Quelle
    The Cascade Runs Ahead of the Flip
    Ähnliche Beiträge
    🔍 Verwandte News

    Auch interessante Nachrichten You Don't Need MIDI-OX Anymore: Building a SysEx Librarian with the Web MIDI API

    Thematisch verwandte Begriffe: Dont, Need, MIDIOX, Anymore · 6 Treffer

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...

    Laden...

    Beiträge werden geladen ...

    Laden...

    Videos werden geladen ...