MIDI is a standard for communication among electronic musical instruments, computers, and related devices. A MIDI file stores musical performance data rather than the multidimensional arrays or token indexes used directly to train music-generation models. It provides a playable way to inspect training examples and generated results. section 13.1.2 section 14.1.3
In a performance-based representation, note-on and note-off messages mark when pitches start and stop. Pitch and velocity values each range from 0 to 127; velocity describes how forcefully a note is played. For example, a note-on message at about 1.03 seconds starts pitch 74 (D5) with velocity 86. Timing, messages, and velocity together preserve details needed for expressive playback. section 14.1.1
The same file format supports two different generation workflows:
- For multitrack generation, represent a piece as a (4, 2, 16, 84) array: four tracks, two bars, 16 steps per bar, and 84 possible pitch positions. Convert the selected pitches back into notes and write a MIDI file to hear the result. The 84 positions belong to this dataset representation, not MIDI’s full 0–127 pitch range. section 13.1 section 13.3.2
- For sequence generation, turn a MIDI performance into note-on, note-off, time-shift, and velocity events. Map those events to integer indexes for a music Transformer; convert generated events back to a playable MIDI file. section 14.1.1 section 14.0
From a multitrack array to something you can hear
Select each step’s pitch with argmax, reshape two bars of 16 steps into 32 rows across four tracks, and create a music21 Part for each track. Accumulate note duration as you walk the steps, append the parts to a Score, then write first_song.midi. Playing the file gives a direct check on the music represented by the array. section 13.3.2
Listing 13.2 Converting pitch numbers to a MIDI file
for i in range(4): #1
last_x = int(midi_note_score[:, i][0])
s = stream.Part()
dur = 0
for idx, x in enumerate(midi_note_score[:, i]): #2
x = int(x)
if (x != last_x or idx % 4 == 0) and idx > 0:
n = note.Note(last_x)
n.duration = duration.Duration(dur)
s.append(n)
dur = 0
last_x = x
dur = dur + 0.25 #3
n = note.Note(last_x)
n.duration = duration.Duration(dur)
s.append(n) #4
parts.append(s)
parts.write("midi","files/first_song.midi")
The conversion listing shows how pitch rows become four timed parts in a playable MIDI file. section 13.3.2
For piano-performance training, MAESTRO v2.0.0 supplies MIDI files. The processor.py module converts them to index sequences and back. Its detailed event-encoding algorithm is not required to train the Transformer; the practical handoff is from a playable performance to numerical training data. section 14.2.1 section 14.2.2
