Introducing another MIDI-to-MakeCode-Arcade song converter!
A simple Python CLI tool that converts your MIDI files into a MakeCode Arcade song ready to play! Unlike previous versions, this tool now supports the base 128 melodic instruments in MIDI and drum notes, allowing for rich-sounding symphony/orchestra-level/DAW music directly in your MakeCode Arcade games without any extra extensions or complex code - just a (really long) song buffer!
Demos
The obligatory demos, listed below. (for a more accurate sound, use the links in the detail below that open directly in the beta editor, as per-chord velocity is still in beta) Press B to toggle the track viewer, and use arrow keys in the track viewer to highlight a track if desired.
Use these links in this detail to open the demos below in the beta editor
It is highly recommended that you open these links in incognito mode or a different browser than normal so that the beta editor is unable to interact with your regular projects or Microsoft (MakeCode Arcade) or GitHub account!
How it Works
Instrument parameter files
Expand detail to read
A 1.5k handwritten YAML file is used to define what all 128 melodic instruments and 61 drum notes sound like. Excerpts below:
melodic_instruments:
# Pianos
- instrument: 0
_comment: Acoustic Grand Piano
waveform: triangle
amp_envelope: { attack: 5, decay: 500, sustain: 200, release: 200, amplitude: 768 }
pitch_envelope: { attack: 0, decay: 0, sustain: 0, release: 0, amplitude: 0 }
amp_lfo: { frequency: 0, amplitude: 0 }
pitch_lfo: { frequency: 0, amplitude: 0 }
- instrument: 12
_comment: Marimba
waveform: sine
amp_envelope: { attack: 5, decay: 300, sustain: 0, release: 200, amplitude: 1024 }
pitch_envelope: { attack: 0, decay: 0, sustain: 0, release: 0, amplitude: 0 }
amp_lfo: { frequency: 0, amplitude: 0 }
pitch_lfo: { frequency: 1, amplitude: 1 }
- note: 38
_comment: Snare Drum 1
start_freq: 800
start_vol: 300
steps:
- { waveform: triangle, target_freq: 100, target_vol: 300, duration: 10 }
- { waveform: noise, target_freq: 0, target_vol: 300, duration: 10 }
- { waveform: noise, target_freq: 0, target_vol: 200, duration: 10 }
- { waveform: noise, target_freq: 0, target_vol: 0, duration: 40 }
- note: 36
_comment: Bass Drum 1
start_freq: 120
start_vol: 1024
steps:
- { waveform: sine, target_freq: 70, target_vol: 850, duration: 25 }
- { waveform: sine, target_freq: 45, target_vol: 350, duration: 35 }
- { waveform: sine, target_freq: 35, target_vol: 0, duration: 50 }
It follows exactly the instrument encoding for MakeCode Arcade songs:
https://github.com/microsoft/pxt/blob/master/pxtlib/music.ts#L23-L94
Then some Python scripting is used to read and map the MIDI file’s note on/off for each instrument into a song! Funnily enough, most of the effort was actually writing the instrument file by hand, as Claude’s attempt resulted in something interesting…I think I’ll let Claude and Gemini help me with coding…
What it Supports
Excerpt from the README:
Standards:
- General MIDI 1 melodic instruments (0-127) and the standard drum kit notes (35-81)
- General MIDI 2 extended drum note range (27-87) on the standard drum kit only
- Roland GS/Yamaha XG SysEx messages for track switching to standard drums only
Features/MIDI messages:
- Tempo changes
- MIDI ports and channels
- Common control changes and Roland GS/Yamaha XG SysEx messages to switch a track to a drum track and back (will only use the standard drum kit notes)
- Per-note velocity (MakeCode Arcade will ignore this for now, but it’s in the song’s output - MakeCode Arcade beta at the time of writing supports it)
See src/midi_to_song/timeline/parser.py to find the exact messages and their values that are supported.
Other Tools / Versions
Here are some other similar tools you should check out!
- @richard’s MIDI converter, which works on the web! It’s better at respecting the MakeCode Arcade song editor’s constraints and using the default instruments. I’d also like to thank Richard for helping me a lot overall with this!
- @WoodysWorkshop’s MIDI converter, which also works on the web and supports lyrics!
- pxt-rtttl to play music written in RTTL syntax.
- arcade-mml to play music written in MML syntax.
And previous versions of MIDI in MakeCode Arcade by me (that are now basically garbage compared to this…)
- ArcadeMIDI which uses images to convey music information and play it back with an extension. Worse performance as JS is managing notes, and less features and is less accurate.
- Musical-Images which also uses images to convey music information and play it back with an extension. Even worse than ArcadeMIDI in every way.
Using it Yourself
To create your own MakeCode Arcade songs, follow the instructions in the README to set up and run the Python tool. (this is not a web app - you need to be able to run Python code somewhere. If you are a Chromebook user and cannot set up Linux usage, try an online environment like GitHub Codespaces, which provides a full Linux environment. Python knowledge is highly recommended - use your favorite search engine or AI assistant or post below or in GitHub issues if you need help or run into any issues!)
The GitHub repo’s README also includes instructions on creating/tuning your own instrument parameter files if desired.
If you want to use the song visualizer yourself, you can find that here (you can import it in an incognito tab/different browser in the beta editor to then paste your own song output). The code was adapted from my original piano synthesia code, which permanently borrowed code from @AqeeAqee’s Karaoke.
Enjoy!