Visualising MIDI files with Python

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 — midi.SetTempoEvent
  • Setting the time signature — midi.TimeSignatureEvent
  • Starting and ending notes — midi.NoteOnEvent and midi.NoteOffEvent respectively
  • Pitch Bending — midi.PitchWheelEvent
  • End of the Track — midi.EndOfTrackEvent

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.

Image for post
Image for post
Culinary Hypersensitivity by Necrophagist — the peaks in blue are the solo.
Image for post
Image for post
Empyreal by Sylosis — The turquoise colour is the sweep picking in the song.
Image for post
Image for post
Mii Plaza theme. This midi file only had one track

Written by

Technical Lead at BJSS. Interested in Automated Testing, Dev practises, Metal, Chiptune. All views my own.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store