From MIDI to Ripchord
January 09, 2025
tl;dr: if you typed “free ripchord presets” and landed here, here’s a bunch of free Ripchord presets thanks to SHLD.
Ripchord is a free, open-source VST for mapping single note presses into chords. It uses XML to store presets in this format:
<?xml version="1.0" encoding="UTF-8"?>
<ripchord>
<preset>
<!-- MIDI note to trigger the chord -->
<input note="60">
<!-- name of the chord and MIDI notes to play -->
<chord name="C Major" notes="60;64;67"/>
</input>
</preset>
</ripchord>
While working on Grandbot, I thought it would be cool if he could generate chord progressions. Rather than trying to program progressions into Grandbot directly though (which would be boring because I don’t know a ton of music theory), I decided to leverage the Ripchord preset format to make norns-ripchord.
Now Grandbot can make a sequence of notes and Norns can adapt those notes into chord progressions. With two Grandbots I can convert the chord progressions back into melodies!
So far, so good. The only problem is that there isn’t a ton of Ripchord presets available online and I didn’t want to use proprietary formats like Scaler or Cthulhu. Musician Paradise has a bunch of great Ripchord presets and I also found SHLD Free MIDI Chord Packs - the only problem with the latter is that my code reads XML and not MIDI files.
So I wrote shld-ripchord. Here’s the basic idea of the script which is using Mido for MIDI parsing:
# SHLD files are named like: Am - I IV V IV.mid
# so we grab the roman numeral name of each chord
name_regex = re.compile('.+ - (.+).mid')
name_match = name_regex.match(source_path)
chord_names = name_match.group(1).split()
# set some global variables
prog_dict = {}
chord_count = 0
chord_notes = []
# I wanted mappings to be on white keys
# starting with middle C
white_key_intervals = [2, 2, 1, 2, 2, 2, 1]
trig_note = 60
# load the MIDI file and iterate over the MIDI messages
midi_file = mido.MidiFile(source_path)
for msg in midi_file:
# accumulate all sequential "note on" notes
if msg.type == "note_on":
chord_notes.append(msg.note)
# when we hit a "note off" MIDI message
# convert collected "note on" messages into a chord
elif msg.type == "note_off" and len(chord_notes) > 0:
# create a new mapping: trigger + name + chord
prog_dict[trig_note] = {}
prog_dict[trig_note]["notes"] = chord_notes
prog_dict[trig_note]["name"] = chord_names[chord_count]
# reset
# increment trig_note in a way that makes all triggers
# land on white keys
trig_note += white_key_intervals[chord_count % len(white_key_intervals)]
chord_count += 1
chord_notes = []
Here’s the code explained:
- Go through each MIDI message in a
.mid
file using Mido - Collect all “note on” messages until we hit a “note off”
- When we hit “note off”, combine collected notes into a chord
- Use the SHLD file name convention as a way to name chords
- Increment the trigger note in a way that lands them on white keys
The reason I didn’t want to be clever about the which trigger note to use:
- Progressions reuse chords;
I IV V IV
uses theIV
chord twice - The lowest note isn’t always the root note
- Placing chords on root notes doesn’t show the chord progression
So I just throw them on the white keys and norns-ripchord
can lock stray notes onto the nearest mapping.
Once I finished this project, I realized I had actually done this before in JavaScript which is kind of embarrassing. It was part of my unfinished attempt to autogenerate Ripchord presets based on sets of chords: ripchord-presets. My life fluttering away one MIDI project at a time.
Anyway, here’s a bunch of free Ripchord chord progression presets ala SHLD.