DEV Community

Cover image for Shipping a Game Boy “Wario Synth” from real MIDI
andy
andy

Posted on

Shipping a Game Boy “Wario Synth” from real MIDI

Wario Synthesis Engine 8-Bit Midi

Turn any song into a Game Boy version

wario.style

GitHub logo b1rdmania / motif

Wario.Style. Game Boy Midi Synthesis Engine. Search any song. Get the 8-bit Game Boy version.

Wario Synthesis Engine 8-Bit Midi

Wario Synth Logo

Turn any song into a Game Boy version.

Live Demo

www.wario.style

About

WAH! 🎮

Type in literally any song. We'll find a MIDI file somewhere on the internet and absolutely demolish it through a janky homebrew Game Boy sound chip running in your browser.

Is it accurate? Sometimes. Is it legal? Probably. Does it slap? Absolutely.

Four glorious channels of chiptune chaos:

  • 🟨 Pulse 1 — screamy lead melodies
  • 🟨 Pulse 2 — whatever pulse 1 forgot
  • 🟩 Wave — chunky bass that hits different
  • Noise — percussion (tssss pshhhh)

Zero samples. Zero server audio. Just raw oscillators having the time of their lives.

wario.style ← go make your favorite song worse

Wario

Features

  • MIDI search from BitMidi and other sources
  • Browser playback with soundfont piano preview
  • Wario Synthesis Engine: procedural Game Boy-style synthesis from parsed MIDI structure
  • Share links with dynamic social previews

Built a fun little web app: search a song, find a real MIDI online, load it, then resynthesize it in-browser with a Game Boy-ish synth engine. Fast MVP, lots of edge cases, a surprising amount of “this slaps”.

What we shipped (MVP)

  • MIDI search + ranking across sources
  • Backend fetch/proxy with SSRF protection
  • Deterministic MIDI parsing + metadata (stable, debuggable)
  • Reliable playback with Web Audio + iOS “tap to enable audio” UX
  • Motif / variation mode (role-mapping: melody/bass/chords/texture → synth layers)

The feature that derailed us: “Download MP3”

We added an export button that:
1) offline-renders (OfflineAudioContext)
2) encodes MP3 in JS (lamejs)
3) triggers a blob download

It used to feel great:

  • “Rendering audio…”
  • “Encoding MP3…”
  • “MP3 downloaded!”

Then browsers started blocking it.

The real problem

Modern browsers often silently block downloads that happen after long async work (render/encode), because the “user gesture” is considered gone. No error, no file, just… nothing.

We tried the usual workarounds (and complexity ballooned):

  • bundle the encoder (avoid CDN globals)
  • two-click “prepare then download”
  • Save File Picker (showSaveFilePicker) where supported
  • pre-open a tab/window on click, then navigate it to the blob

At some point the export UX became the least reliable part of the app, so we removed the Download MP3 button instead of shipping something flaky.

What we learned

  • Reliability beats cleverness: a flaky button poisons trust.
  • Browser policies are product constraints: autoplay unlock + download gesture rules define your UX.
  • Determinism makes iteration fun: stable parsing/metadata keeps debugging sane.

How we can level it up next

  • Build our own MIDI library: crawl/cache “known good” MIDIs, normalize metadata, dedupe, rank by “sounds good in our synth”.
  • Better musical intelligence (still lightweight): improved role mapping, basic key/scale heuristics, smarter drum/noise handling.
  • Bring export back properly: either server-side rendering/export or a deliberate “Save…” flow that’s actually reliable cross-browser.

Still: turning random MIDIs into crunchy Game Boy performances is stupidly fun—and it’s a great playground for audio, MIDI weirdness, and shipping fast.

Top comments (0)