Plug — I’ve since done even more work with MIDI and created a MIDI to LSDJ app in Python
I’m really into music, If you spend 5 minutes talking to me you’ll probably realise that I care a little too much about how particular songs, albums and bands make me feel when I listen to them and why other bands just don’t cut the audio mustard.
I have a growing collection of notation files on my computer for my favourite songs, these are often in Guitar Pro (me being a guitar player) or in MIDI. The latter comes in very handy when I want to record myself playing the guitar parts as I can just import the drum track and the tempo and time signature changes are brought in with it.
I found this awesome Python library for parsing MIDI files and decided to hook it up to Matplotlib to see if I could visualise the notes in the file to make a nifty little representation of the song.
I’d used Matplotlib before at a hack day where we were parsing DICOM files and using Matplotlib to plot the x, y and z values we were able to build a 3D representation of the data in the file relatively easy.
Converting MIDI to a line
The python-midi library gives you a really helpful method called
read_midifile which handles the loading and parsing of the MIDI file.
The result of the
read_midifile method is a list of MIDI tracks which each contain a list of MIDI events such as:
- Setting the tempo —
- Setting the time signature —
- Starting and ending notes —
- Pitch Bending —
- End of the Track —
All of the events have a tick associated with it, this is relative by default but if you call
make_ticks_abs() on the loaded file it will return the ticks as absolute values. It can be a little confusing when looking at the events with relative ticks as you’ll see loads of a
0 ticks followed by high number ones, for the sake of plotting notes on a chart I used absolute ticks.
To get the pitch of the note in
midi.NoteOnEvents there’s a
.pitch property so by collecting these
NoteOnEvents and collecting the absolute tick and pitch values for each note we then have data to draw.
To plot these values in Matplotlib we just need to pass it a list of x and y values, for multiple tracks we just add more x and y values such as:
pyplot.plot(track1_ticks, track1_pitches, track2_ticks, track2_pitches)
Or create a list of ticks and pitches and then unpack that list into the
plot function. Finally we just need to call
pyplot.show() which will bring up a rendered chart.
You can find my final file on my GitHub repo — midivis.
The end result
Here’s a bunch of songs I have on my computer put through my program.