Following Section 1.2.1 of [Müller, FMP, Springer 2015], we look in this notebook at a symbolic music representation called MIDI.
import os
import matplotlib
from matplotlib import pyplot as plt
import pretty_midi
import pandas as pd
import IPython.display as ipd
fn = 'FMP_C1_F10_Beethoven_Fifth-MM1-20_MIDI-Orchestra.mid'
# generating a table of all notes
midi_data = pretty_midi.PrettyMIDI(fn)
midi_list = []
for instrument in midi_data.instruments:
instrument_name = instrument.name
for note in instrument.notes:
start = note.start
end = note.end
pitch = note.pitch
velocity = note.velocity
midi_list.append([start, end, pitch, velocity, instrument_name])
midi_list = sorted(midi_list, key=lambda x: x[0])
df = pd.DataFrame(midi_list, columns=['Start', 'End', 'Pitch', 'Velocity', 'Instrument'])
html = df.to_html(index=False, float_format='%.2f')
ipd.HTML(html)
#synthesizing the MIDI data
fs = 22050
audio_data = midi_data.synthesize(fs=fs)
ipd.Audio(audio_data, rate=fs)
# plotting with velocity as "color"
plt.figure(figsize=(15, 10))
ax = plt.gca()
starts = []
ends = []
pitches = []
for instrument in midi_data.instruments:
instrument_name = instrument.name
for note in instrument.notes:
start = note.start
end = note.end
pitch = note.pitch
velocity = note.velocity
rect = matplotlib.patches.Rectangle((start, pitch - 0.5), end-start, 1, linewidth=1,
edgecolor='k', facecolor=str(velocity / 128), alpha=0.5)
ax.add_patch(rect)
starts.append(start)
ends.append(end)
pitches.append(pitch)
plt.ylim([min(pitches)-0.5, max(pitches) + 0.5])
plt.xlim([min(min(starts), 0), max(ends)])
plt.xlabel('Time (seconds)')
plt.ylabel('Frequency (pitch)')
plt.grid()
ax.set_axisbelow(True)
# plotting with instrument as "color"
instruments = sorted(set(instrument.name for instrument in midi_data.instruments))
cm = plt.get_cmap('gist_rainbow')
instrument_colors = [cm(i/len(instruments)) for i in range(len(instruments))]
plt.figure(figsize=(15, 10))
ax = plt.gca()
starts = []
ends = []
pitches = []
for instrument in midi_data.instruments:
instrument_name = instrument.name
instrument_color = instrument_colors[instruments.index(instrument_name)]
for note in instrument.notes:
start = note.start
end = note.end
pitch = note.pitch
velocity = note.velocity
rect = matplotlib.patches.Rectangle((start, pitch - 0.5), end-start, 1, linewidth=1,
edgecolor='k', facecolor=instrument_color, alpha=0.5)
ax.add_patch(rect)
starts.append(start)
ends.append(end)
pitches.append(pitch)
plt.ylim([min(pitches)-0.5, max(pitches) + 0.5])
plt.xlim([min(min(starts), 0), max(ends)])
plt.xlabel('Time (seconds)')
plt.ylabel('Frequency (pitch)')
plt.grid()
ax.set_axisbelow(True)
ax.legend([matplotlib.patches.Patch(linewidth=1, edgecolor='k', facecolor=c, alpha=0.5) for c in instrument_colors],
instruments)
Acknowledgment: This notebook was created by Frank Zalkow and Meinard Müller.