How do you keep Web MIDI from crashing a 1983 synthesizer?
Why writing Web MIDI code for 8-bit CPUs from the 1980s is an absolute timing nightmare, and how to safely control data flows on vintage hardware directly from your browser.
Why writing Web MIDI code for 8-bit CPUs from the 1980s is an absolute timing nightmare, and how to safely control data flows on vintage hardware directly from your browser.
Modern browsers run fast. Your system processor operates in gigahertz, handles multi-threaded operations, and loads gigabytes of data in milliseconds.
The microprocessor inside a vintage 1983 Yamaha DX7 is an 8-bit Hitachi 6305 running at a clock speed of 2 MHz, with a tiny 256-byte RAM buffer.
When you try to bridge these two eras using the modern Web MIDI API, you run headfirst into a classic retrocomputing bottleneck: buffer overflow. Send data too fast, and the synthesizerβs CPU hangs, drops packages, or corrupts the internal sound memory completely.
In the 80s, MIDI physical hardware operated over a current loop running at 31,250 bits per second. While slow, the bandwidth was constant and predictable.
Today, most computer music setups use modern USB-to-MIDI adapters. Modern computers send USB packets at lightning-fast speeds. A cheap, bufferless adapter receives the data at high USB bandwidths, and instantly attempts to serialize and dump it down the MIDI out pin.
Because standard MIDI lacks hardware handshaking lines (no RTS/CTS pins), there's no physical way for the DX7 to tell the browser: "Hey, stop sending data, I'm writing the last preset block to SRAM right now."
To solve this in JavaScript, we have to enforce a custom software flow throttle:
// Chunking and pacing SysEx transmission arrays
async function sendSysExWithPacing(midiOutput, rawSysExBytes) {
const CHUNK_SIZE = 256; // Limit blocks to prevent buffer floods
const INTER_CHUNK_DELAY = 60; // Milliseconds to wait between packets
for (let i = 0; i < rawSysExBytes.length; i += CHUNK_SIZE) {
const chunk = rawSysExBytes.slice(i, i + CHUNK_SIZE);
midiOutput.send(chunk);
// Wait to allow the vintage 8-bit CPU to write block to EEPROM
await new Promise(resolve => setTimeout(resolve, INTER_CHUNK_DELAY));
}
}
Once you establish a reliable hardware communication link, the next hurdle is decoding the data. Back in the 80s, the MIDI spec defined how notes were triggered, but left the system exclusive (SysEx) parameter format entirely up to manufacturers.
This means every single vintage synthesizer has its own undocumented, proprietary byte structure:
Because Web MIDI allows a website to flash firmware or write raw system-exclusive bytes directly to external physical USB hardware, browsers treat it with extreme security care.
Browsers like Google Chrome and Microsoft Edge require explicit user approval via permissions before allowing websites to communicate over MIDI. Safari and Firefox block the Web MIDI API entirely out of caution regarding fingerprinting and hardware injection vulnerabilities.
We built knob.monster to replace dusty unsigned desktop utilities. Connect your hardware synthesizer directly to a browser tab, click back up, and organize your presets in a modern, searchable cloud library.