Let's work with an actual song. In this notebook we'll learn how to use Markov chains to learn patterns from actual songs and generate new material. We will read in music from the song Billi Jean, train a Markov model, and resynthesize Billie Jean using the trained Markov model. Things get weird quickly...
Install external libraries and import them into your notebok session
# install external libraries for sound playback
from IPython.display import clear_output
!pip install -q git+https://github.com/davidkant/mai#egg=mai;
!apt-get -qq update
!apt-get -qq install -y libfluidsynth1
!apt-get install lame
!git clone https://github.com/davidkant/mai.git
clear_output()
# imports
import mai
import random
import pretty_midi
import matplotlib.pyplot as plt
import copy
import IPython.display
Using TensorFlow backend.
We'll also define a function here for plotting. Don't worry about understanding this cell.
def plot_melodies(original_pitches, new_pitcjes, num_notes=45):
"""Plot original melody and new melody."""
plt.figure(figsize=(9,3))
plt.plot(original_pitches[0:num_notes])
plt.scatter(range(num_notes), original_pitches[0:num_notes])
plt.plot(new_pitches[0:num_notes])
plt.scatter(range(num_notes), new_pitches[0:num_notes])
plt.ylim([min(original_pitches)-1, max(original_pitches)+1])
plt.xlabel('time (in numbe of notes)')
plt.ylabel('pitch')
plt.title("original melody (blue) and new melody (orange)");
First load in a MIDI file of the song Billie Jean. We are using a Python package called pretty_midi
to read and manipulate MIDI data. I have provided the MIDI file Billie_Jean.mid
in the aim80L
Python package.
# load midi file
midi_data = pretty_midi.PrettyMIDI('mai/resources/midi/Billie_Jean.mid')
# and make a copy for our resynthesized version
altered_midi_data = copy.deepcopy(midi_data)
MIDI files are often organized with multiple voices or instruments, which are stored in an instruments
list. Run the cell below to see the instruments list. Hopefully the file you are using names its instruments! Otherwise it'll be difficult to know which voice corresponds to which instrument...
# display all instruments
midi_data.instruments
[Instrument(program=53, is_drum=False, name=""), Instrument(program=5, is_drum=False, name=""), Instrument(program=27, is_drum=False, name=""), Instrument(program=28, is_drum=False, name=""), Instrument(program=49, is_drum=False, name=""), Instrument(program=7, is_drum=False, name=""), Instrument(program=63, is_drum=False, name=""), Instrument(program=88, is_drum=False, name=""), Instrument(program=62, is_drum=False, name=""), Instrument(program=28, is_drum=False, name=""), Instrument(program=50, is_drum=False, name=""), Instrument(program=35, is_drum=False, name=""), Instrument(program=0, is_drum=True, name="")]
Now indicate the instrument you'd like to work with according to its index in the list.
# instrument to work with
instrument_index = 0
note: Since instruments arn't named in this file, here are a few:
midi_data.instrument[0]
midi_data.instrument[-1]
midi_data.instrument[-2]
midi_data.instrument[-3]
We are going to extract the pitch and rhythm information from the vocal melody, turning it into two lists of numbers, one representing pitch and the other duration. Don't worry about understanding the programming in this cell.
# select instrument from list
instrument = midi_data.instruments[instrument_index]
# extract pitch to list
original_pitches = [note.pitch for note in instrument.notes]
# extract durations to list
original_durs = [(n2.start - n1.start) for n1,n2 in zip(instrument.notes[:-1], instrument.notes[1:])]
Print the pitches and durations lists.
print(original_pitches)
[61, 61, 61, 59, 57, 59, 57, 61, 57, 57, 59, 57, 61, 61, 61, 61, 61, 59, 57, 59, 57, 61, 59, 57, 56, 54, 54, 56, 54, 54, 56, 54, 54, 56, 54, 54, 57, 59, 57, 56, 54, 57, 56, 54, 57, 56, 54, 57, 56, 54, 61, 61, 61, 59, 57, 59, 57, 61, 57, 57, 59, 57, 61, 61, 61, 61, 61, 59, 57, 59, 57, 61, 59, 57, 56, 54, 54, 56, 54, 54, 56, 54, 54, 56, 54, 66, 64, 66, 64, 66, 69, 66, 69, 66, 66, 64, 66, 61, 66, 64, 66, 66, 66, 64, 66, 68, 66, 64, 66, 64, 66, 64, 66, 66, 66, 66, 69, 66, 66, 64, 66, 61, 66, 62, 62, 62, 62, 64, 66, 66, 65, 65, 65, 65, 66, 68, 66, 68, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 66, 64, 61, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 61, 61, 61, 59, 57, 59, 57, 61, 57, 57, 59, 57, 61, 61, 61, 61, 61, 59, 57, 59, 57, 61, 59, 57, 56, 54, 54, 56, 54, 54, 56, 54, 54, 56, 54, 54, 57, 59, 57, 56, 54, 57, 56, 54, 57, 56, 54, 57, 56, 54, 61, 61, 61, 59, 57, 59, 57, 61, 57, 57, 59, 57, 61, 61, 61, 61, 61, 59, 57, 59, 57, 61, 59, 57, 56, 54, 54, 56, 54, 54, 56, 54, 54, 56, 54, 66, 64, 66, 64, 66, 69, 66, 69, 66, 66, 64, 66, 61, 66, 64, 66, 66, 66, 64, 66, 68, 66, 64, 66, 64, 66, 64, 66, 66, 66, 66, 69, 66, 66, 64, 66, 61, 66, 62, 62, 62, 62, 64, 66, 66, 65, 65, 65, 65, 66, 68, 66, 68, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 66, 64, 61, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 66, 64, 61, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 66, 64, 61, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 69, 71, 69, 68, 66, 66, 66, 73, 71, 71, 66, 62, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61, 66, 66, 64, 61, 61, 66, 66, 64, 61]
print(original_durs)
[0.22395833333333215, 0.28125, 0.234375, 0.265625, 0.265625, 0.5, 0.2421875, 0.2552083333333357, 0.125, 0.1328125, 0.23177083333333215, 0.23958333333333215, 0.7552083333333357, 0.2473958333333286, 0.2395833333333357, 0.2786458333333357, 0.2421875, 0.2421875, 0.2578125, 0.2526041666666643, 0.234375, 0.5234375, 0.4947916666666643, 0.2630208333333357, 0.2630208333333357, 1.6979166666666643, 0.1354166666666643, 0.1197916666666714, 0.7421875, 0.1510416666666643, 0.1171875, 0.7395833333333357, 0.1380208333333286, 0.109375, 2.5, 0.2421875, 0.2604166666666714, 0.4947916666666643, 0.2421875, 0.2708333333333357, 1.7395833333333286, 0.1302083333333357, 0.140625, 0.7213541666666643, 0.1354166666666714, 0.1354166666666643, 0.7291666666666643, 0.1302083333333357, 0.1276041666666643, 4.7578125, 0.2239583333333357, 0.28125, 0.234375, 0.265625, 0.265625, 0.5, 0.2421875, 0.2552083333333357, 0.125, 0.1328125, 0.2317708333333286, 0.2395833333333357, 0.7552083333333357, 0.2473958333333286, 0.2395833333333357, 0.2786458333333357, 0.2421875, 0.2421875, 0.2578125, 0.2526041666666643, 0.234375, 0.5234375, 0.4947916666666643, 0.2630208333333357, 0.2630208333333357, 1.6979166666666643, 0.1354166666666643, 0.1197916666666714, 0.7552083333333286, 0.1380208333333357, 0.1197916666666643, 0.734375, 0.140625, 0.1171875, 4.236979166666671, 0.2447916666666572, 0.1197916666666714, 0.2604166666666714, 0.1380208333333286, 0.46875, 0.5234375, 0.2447916666666714, 0.2395833333333286, 0.1276041666666714, 0.2473958333333286, 0.1197916666666714, 1.0286458333333286, 0.1197916666666714, 0.1302083333333286, 0.1276041666666714, 0.11979166666665719, 0.5130208333333428, 0.1354166666666572, 0.1328125, 0.2734375, 0.46875, 1.9739583333333428, 0.2604166666666572, 0.2421875, 0.1328125, 0.2604166666666714, 0.1276041666666714, 0.2942708333333286, 0.6588541666666714, 0.11979166666665719, 0.1354166666666714, 0.2630208333333286, 0.1380208333333428, 0.2786458333333286, 0.1302083333333286, 0.9557291666666714, 0.1302083333333286, 0.1197916666666714, 0.2552083333333286, 0.1119791666666714, 0.1354166666666714, 0.125, 0.3984375, 0.7109375, 0.2604166666666572, 0.2604166666666714, 0.1223958333333286, 0.1328125, 0.1302083333333428, 0.3854166666666572, 0.4895833333333428, 0.2421875, 0.75, 0.2135416666666572, 0.2734375, 0.265625, 0.5026041666666714, 0.2604166666666714, 0.2421875, 0.46875, 0.5078125, 0.9947916666666572, 0.2604166666666714, 0.2552083333333286, 0.2708333333333428, 0.2369791666666572, 0.2421875, 0.4895833333333428, 0.2942708333333286, 0.4635416666666714, 0.5104166666666572, 0.2473958333333428, 0.2395833333333286, 1.4869791666666714, 0.5, 0.2604166666666572, 0.2526041666666714, 0.2838541666666714, 0.4791666666666572, 0.2682291666666714, 0.5026041666666714, 2.46875, 0.234375, 0.2708333333333286, 0.4817708333333286, 0.2552083333333428, 0.2682291666666572, 1.4895833333333428, 0.4921875, 0.2578125, 0.2473958333333286, 0.2630208333333286, 0.4921875, 0.2630208333333428, 0.5026041666666572, 4.736979166666671, 0.2239583333333286, 0.28125, 0.234375, 0.265625, 0.265625, 0.5, 0.2421875, 0.2552083333333428, 0.125, 0.1328125, 0.2317708333333286, 0.2395833333333286, 0.7552083333333428, 0.2473958333333286, 0.2395833333333286, 0.2786458333333428, 0.2421875, 0.2421875, 0.2578125, 0.2526041666666572, 0.234375, 0.5234375, 0.4947916666666714, 0.2630208333333286, 0.2630208333333428, 1.6979166666666572, 0.1354166666666714, 0.1197916666666714, 0.7421875, 0.1510416666666572, 0.1171875, 0.7395833333333428, 0.1380208333333286, 0.109375, 2.5, 0.2421875, 0.2604166666666714, 0.4947916666666572, 0.2421875, 0.2708333333333428, 1.7395833333333286, 0.1302083333333286, 0.140625, 0.7213541666666714, 0.1354166666666714, 0.1354166666666572, 0.7291666666666714, 0.1302083333333286, 0.1276041666666714, 4.757812499999986, 0.2239583333333428, 0.28125, 0.234375, 0.265625, 0.265625, 0.5, 0.2421875, 0.2552083333333428, 0.125, 0.1328125, 0.23177083333331439, 0.2395833333333428, 0.7552083333333428, 0.24739583333331439, 0.2395833333333428, 0.2786458333333428, 0.2421875, 0.2421875, 0.2578125, 0.2526041666666572, 0.234375, 0.5234375, 0.4947916666666572, 0.2630208333333428, 0.2630208333333428, 1.6979166666666572, 0.1354166666666572, 0.11979166666668561, 0.7552083333333144, 0.1380208333333428, 0.11979166666665719, 0.734375, 0.140625, 0.1171875, 4.236979166666686, 0.2447916666666572, 0.11979166666665719, 0.2604166666666856, 0.13802083333331439, 0.46875, 0.5234375, 0.24479166666668561, 0.23958333333331439, 0.12760416666668561, 0.24739583333331439, 0.11979166666668561, 1.0286458333333144, 0.11979166666668561, 0.13020833333331439, 0.12760416666668561, 0.11979166666665719, 0.5130208333333428, 0.1354166666666572, 0.1328125, 0.2734375, 0.46875, 1.9739583333333428, 0.2604166666666572, 0.2421875, 0.1328125, 0.2604166666666572, 0.12760416666668561, 0.2942708333333144, 0.6588541666666856, 0.11979166666665719, 0.1354166666666572, 0.2630208333333428, 0.1380208333333428, 0.2786458333333144, 0.1302083333333428, 0.9557291666666572, 0.1302083333333428, 0.11979166666665719, 0.2552083333333428, 0.11197916666665719, 0.13541666666668561, 0.125, 0.3984375, 0.7109375, 0.2604166666666572, 0.2604166666666572, 0.12239583333334281, 0.1328125, 0.1302083333333428, 0.3854166666666572, 0.4895833333333428, 0.2421875, 0.75, 0.2135416666666572, 0.2734375, 0.265625, 0.5026041666666572, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 0.9947916666666572, 0.2604166666666572, 0.2552083333333428, 0.2708333333333428, 0.2369791666666572, 0.2421875, 0.4895833333333428, 0.2942708333333144, 0.4635416666666856, 0.5104166666666572, 0.2473958333333428, 0.23958333333331439, 1.4869791666666856, 0.5, 0.2604166666666572, 0.2526041666666572, 0.2838541666666856, 0.4791666666666572, 0.2682291666666572, 0.5026041666666856, 4.7265625, 0.2135416666666572, 0.2734375, 0.265625, 0.5026041666666572, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 0.9947916666666572, 0.2604166666666572, 0.2552083333333428, 0.2708333333333428, 0.2369791666666572, 0.2421875, 0.4895833333333428, 0.2942708333333144, 0.4635416666666856, 0.5104166666666572, 0.2473958333333428, 0.23958333333331439, 1.4869791666666856, 0.5, 0.2604166666666572, 0.2526041666666572, 0.2838541666666856, 0.4791666666666572, 0.2682291666666572, 0.5026041666666856, 2.46875, 0.234375, 0.2708333333333144, 0.4817708333333428, 0.2552083333333428, 0.2682291666666572, 1.4895833333333428, 0.4921875, 0.2578125, 0.24739583333331439, 0.2630208333333428, 0.4921875, 0.2630208333333428, 0.5026041666666572, 18.481770833333343, 0.234375, 0.2708333333333144, 0.4817708333333428, 0.2552083333333428, 0.2682291666666572, 1.4895833333333428, 0.4921875, 0.2578125, 0.24739583333331439, 0.2630208333333428, 0.4921875, 0.2630208333333428, 0.5026041666666572, 4.739583333333343, 0.2135416666666572, 0.2734375, 0.265625, 0.5026041666666572, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 0.9947916666666572, 0.2604166666666572, 0.2552083333333428, 0.2708333333333428, 0.2369791666666572, 0.2421875, 0.4895833333333428, 0.2942708333333144, 0.4635416666666856, 0.5104166666666572, 0.2473958333333428, 0.23958333333331439, 1.4869791666666856, 0.5, 0.2604166666666572, 0.2526041666666572, 0.2838541666666856, 0.4791666666666572, 0.2682291666666572, 0.5026041666666856, 2.46875, 0.234375, 0.2708333333333144, 0.4817708333333428, 0.2552083333333428, 0.2682291666666572, 1.4895833333333428, 0.4921875, 0.2578125, 0.24739583333331439, 0.2630208333333428, 0.4921875, 0.2630208333333428, 0.5026041666666572, 4.739583333333343, 0.2135416666666572, 0.2734375, 0.265625, 0.5026041666666572, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125, 1.265625, 0.21354166666662877, 0.2734375, 0.265625, 0.5026041666666856, 0.2604166666666856, 0.2421875, 0.46875, 0.5078125]
And... play it. Just the first 30 notes or so, it's a long song.
# num notes
n = 35
# plot
mai.make_music_plot(pitches=original_pitches[:n], durs=original_durs[:n])
# play
mai.make_music(pitches=original_pitches[:n], durs=original_durs[:n], pgm=35)
Train a Markov model on the sequnce of pitches extracted from the vocal meldoy. This is where you specify what order
Markov chain you'd like to use.
# what order?
order = 1
# create a markov chain instance
mark = mai.markov.Markov()
# then learn a transition table from data
mark.train(original_pitches, order=order)
View the transition table
# plot transition table
mark.plot_transition_matrix(figscale=0.2)
# show length of transition table
len(mark.transitions)
38
# show transition table
mark.print_transitions()
(61,) -> 61 : 40 (61,) -> 59 : 12 (59,) -> 57 : 26 (57,) -> 59 : 14 (57,) -> 61 : 12 (61,) -> 57 : 4 (57,) -> 57 : 4 (57,) -> 56 : 12 (56,) -> 54 : 24 (54,) -> 54 : 14 (54,) -> 56 : 12 (54,) -> 57 : 8 (54,) -> 61 : 2 (54,) -> 66 : 2 (66,) -> 64 : 44 (64,) -> 66 : 20 (66,) -> 69 : 14 (69,) -> 66 : 6 (66,) -> 66 : 62 (66,) -> 61 : 4 (61,) -> 66 : 36 (66,) -> 68 : 6 (68,) -> 66 : 14 (66,) -> 62 : 10 (62,) -> 62 : 6 (62,) -> 64 : 2 (66,) -> 65 : 2 (65,) -> 65 : 6 (65,) -> 66 : 2 (64,) -> 61 : 26 (69,) -> 71 : 8 (71,) -> 69 : 8 (69,) -> 68 : 8 (66,) -> 73 : 8 (73,) -> 71 : 8 (71,) -> 71 : 8 (71,) -> 66 : 8 (62,) -> 61 : 8
Now the fun part, we generate a new vocal melody using the Markov model learned from the original. Note that this cell first sets the initial Markov state to be the first order
number of notes from the original melody, then generates a new melody with the same number of notes as the original. Important: you do not need to edit any code in this cell when changing the order.
# generate a new melody
new_pitches = mark.choice(k=len(original_pitches)-order, suppress_errors=True)
Note: If your Markov model produces the error 'Current state not found in transition table'
, you can supress it by passing the value True
to the argument supress_errors
in the mark.choose()
function call.
# print the new music
print(new_pitches)
[61, 59, 57, 61, 66, 66, 66, 69, 71, 71, 69, 68, 66, 64, 61, 66, 62, 61, 66, 69, 71, 66, 64, 61, 66, 64, 66, 73, 71, 71, 71, 66, 64, 61, 61, 61, 61, 57, 61, 59, 57, 59, 57, 59, 57, 61, 61, 59, 57, 57, 61, 61, 66, 62, 62, 64, 61, 66, 62, 62, 62, 61, 61, 59, 57, 56, 54, 56, 54, 54, 54, 56, 54, 57, 59, 57, 59, 57, 59, 57, 56, 54, 56, 54, 54, 54, 56, 54, 54, 54, 56, 54, 57, 61, 59, 57, 61, 66, 69, 68, 66, 64, 66, 64, 61, 61, 66, 69, 71, 69, 71, 66, 66, 64, 61, 66, 66, 66, 73, 71, 69, 66, 69, 68, 66, 64, 61, 59, 57, 57, 59, 57, 56, 54, 57, 56, 54, 54, 57, 56, 54, 54, 56, 54, 66, 66, 68, 66, 66, 62, 62, 62, 62, 61, 61, 66, 66, 66, 66, 66, 68, 66, 69, 71, 66, 64, 61, 61, 66, 66, 66, 66, 68, 66, 66, 62, 64, 61, 61, 57, 59, 57, 56, 54, 54, 57, 59, 57, 61, 57, 61, 61, 61, 66, 64, 66, 64, 61, 66, 66, 66, 66, 64, 61, 59, 57, 61, 66, 66, 62, 62, 62, 61, 61, 57, 59, 57, 61, 66, 66, 64, 61, 57, 56, 54, 57, 59, 57, 56, 54, 56, 54, 56, 54, 54, 54, 54, 54, 57, 56, 54, 54, 54, 56, 54, 57, 56, 54, 54, 57, 56, 54, 66, 69, 68, 66, 69, 71, 66, 66, 66, 64, 61, 61, 61, 61, 59, 57, 59, 57, 61, 66, 66, 64, 66, 69, 71, 71, 69, 71, 69, 71, 66, 66, 66, 62, 61, 61, 59, 57, 61, 66, 64, 66, 62, 61, 61, 66, 64, 66, 66, 66, 69, 68, 66, 64, 66, 64, 66, 69, 68, 66, 62, 61, 61, 61, 57, 61, 59, 57, 59, 57, 56, 54, 57, 59, 57, 59, 57, 56, 54, 56, 54, 66, 73, 71, 66, 61, 59, 57, 56, 54, 57, 61, 59, 57, 61, 61, 66, 62, 62, 62, 62, 62, 62, 62, 62, 64, 61, 66, 62, 62, 61, 61, 61, 66, 66, 69, 66, 64, 61, 66, 66, 69, 68, 66, 64, 61, 59, 57, 59, 57, 56, 54, 66, 69, 66, 64, 66, 73, 71, 69, 71, 71, 71, 69, 66, 64, 61, 61, 59, 57, 59, 57, 59, 57, 59, 57, 61, 59, 57, 59, 57, 61, 61, 61, 66, 68, 66, 69, 68, 66, 64, 61, 66, 64, 66, 66, 66, 61, 61, 66, 66, 62, 62, 62, 61, 61, 66, 64, 61, 59, 57, 59, 57, 61, 66, 66, 64, 66, 64, 61, 66, 68, 66, 66, 64, 61, 66, 66, 66, 66, 64, 61, 61, 66, 73, 71, 69, 68, 66, 64, 66, 69, 71, 66, 66, 66, 66, 62, 61, 61, 66, 66, 66, 69, 71, 71, 69, 68, 66, 64, 61, 61, 61, 61, 61, 61, 66, 64, 61, 61, 61, 61, 59, 57, 59, 57, 59, 57, 59]
Let's also plot them. Here the the original melody (in blue) and the new melody (in orange) are on the same plot. How do they compare?
plot_melodies(original_pitches, new_pitches, num_notes=45)
We'll start by resynthesizing the altered voice solo. Since we've only manipulated pitch, we'll use the rhythm from the original vocal line. This may take a few moments... Warning! Turn down your volume before you hit play b/c sometimes the player makes loud static --- usually if you synthesize MIDI into silence.
# num notes
n = 35
# plot
mai.make_music_plot(pitches=new_pitches[:n], durs=original_durs[:n])
# play
mai.make_music(pitches=new_pitches[:n], durs=original_durs[:n], pgm=35)
Let's add that altered voice to the band and listen to the entire band. We do this by overwriting the voice in altered_midi_data
, which is a copy of the original midi file we read it in way back at the beginning of this notebook.
# loop through original notes and change the pitch
for i,new_pitch in enumerate(new_pitches):
instrument.notes[i].pitch = new_pitch
# this time replace the original instrument with your new one
altered_midi_data.instruments[instrument_index] = instrument
# synthesize midi to audio
x = altered_midi_data.fluidsynth(fs=22050)
# convert to mp3 and listen
mai.io.play_mp3(x, sr=22050)
Go back and try a few other instruments. Try different orders as well! Can you get a sense for how order affects the resynthesized music?