{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# `pretty_midi` tutorial\n", "\n", "This tutorial goes over the functionality of [pretty_midi](http://github.com/craffel/pretty_midi), a Python library for creating, manipulating, and extracting information from MIDI files. For more information, check [the docs](http://craffel.github.io/pretty-midi/)." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Uncomment to install dependecies to run on Colab:\n", "#!sudo apt-get install fluidsynth\n", "#!pip install pretty_midi mir_eval pyfluidsynth\n", "\n", "# For Python2.6 compatibility\n", "from __future__ import print_function\n", "\n", "import pretty_midi\n", "import numpy as np\n", "# For plotting\n", "import mir_eval.display\n", "import librosa.display\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline\n", "# For putting audio in the notebook\n", "import IPython.display\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Building a MIDI file from scratch\n", "\n", "To start, we'll build a MIDI sequence from the ground up. More specifically, we'll build up a MIDI \"object\" using `pretty_midi`'s representation of MIDI (which we can optionally write out to a MIDI file later on). This representation is actually a little different than standard MIDI files (it's intended to be less ambiguous and a little easier to work with), but the two are mostly interchangeable. Relevant differences will be pointed out as we go.\n", "\n", "### The `PrettyMIDI` class\n", "\n", "The `PrettyMIDI` class is the main container in `pretty_midi`. It stores not only all of the events that constitute the piece, but also all of the timing information, meta-events (like key signature changes), and utility functions for manipulating, writing out, and inferring information about the MIDI data it contains." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Construct a PrettyMIDI object.\n", "# We'll specify that it will have a tempo of 80bpm.\n", "pm = pretty_midi.PrettyMIDI(initial_tempo=80)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### The `Instrument` class\n", "\n", "One of the most important functions of the `PrettyMIDI` class is to hold a `list` of `Instrument` class instances. Each `Instrument` is able to store different events (for example, notes) which are meant to be played on a given general MIDI instrument (for example, instrument 42, \"Cello\"). The `Instrument` class also has functions for extracting useful information based solely on the events that occur on that particular instrument." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[]\n" ] } ], "source": [ "# The instruments list from our PrettyMIDI instance starts empty\n", "print(pm.instruments)" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Let's add a Cello instrument, which has program number 42.\n", "# pretty_midi also keeps track of whether each instrument is a \"drum\" instrument or not\n", "# because drum/non-drum instruments share program numbers in MIDI.\n", "# You can also optionally give the instrument a name,\n", "# which corresponds to the MIDI \"instrument name\" meta-event.\n", "inst = pretty_midi.Instrument(program=42, is_drum=False, name='my cello')\n", "pm.instruments.append(inst)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Event containers\n", "\n", "`pretty_midi` has individual classes for holding MIDI events: `Note`, `PitchBend`, and `ControlChange`. These classes store information analogous to their corresponding MIDI events. The `Instrument` class has separate `list`s for each of these event types.\n", "\n", "#### Note\n", "\n", "The `Note` class represents a MIDI note, which has a pitch, a start time, and and end time. Notes have a pitch number from 0 to 127, representing the notes from C-1 to G9. In addition, notes have a velocity (volume) from 1 to 127, from quietest to loudest. The way `pretty_midi` stores notes is slightly different from standard MIDI, in the sense that in MIDI the note-on and note-off events are separate and their correspondences must be guessed from the MIDI stream. `pretty_midi` keeps the start and end times of a note coupled together, so things are less ambiguous. Furthermore, `pretty_midi` stores all times in terms of actual wall clock time from the start of the MIDI sequence, rather than in \"ticks\" (discussed further below). This is much easier to work with!" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "[Note(start=0.200000, end=1.100000, pitch=60, velocity=100), Note(start=0.600000, end=1.700000, pitch=62, velocity=100), Note(start=1.000000, end=2.300000, pitch=64, velocity=100)]\n" ] } ], "source": [ "# Let's add a few notes to our instrument\n", "velocity = 100\n", "for pitch, start, end in zip([60, 62, 64], [0.2, 0.6, 1.0], [1.1, 1.7, 2.3]):\n", " inst.notes.append(pretty_midi.Note(velocity, pitch, start, end))\n", "print(inst.notes)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Pitch bends\n", "\n", "Since MIDI notes are all defined to have a specific integer pitch value, in order to represent arbitrary pitch frequencies we need to use pitch bends. A `PitchBend` class in `pretty_midi` holds a time (in seconds) and a pitch offset. The pitch offset is an integer in the range [-8192, 8191], which in General MIDI spans the range from -2 to +2 semitones. As with `Note`s, the `Instrument` class has a `list` for `PitchBend` class instances." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "# We'll just do a 1-semitone pitch ramp up\n", "n_steps = 512\n", "bend_range = 8192//2\n", "for time, pitch in zip(np.linspace(1.5, 2.3, n_steps),\n", " range(0, bend_range, bend_range//n_steps)):\n", " inst.pitch_bends.append(pretty_midi.PitchBend(pitch, time))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Control changes\n", "\n", "The `Instrument` class also holds control changes. Control changes include things like modulation, reverb, etc., which may or may not be supported by a given General MIDI synthesizer. As usual, they are stored in an `Instrument`'s `control_changes` `list`. We won't be covering them here." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Putting it all together\n", "\n", "To give you a taste of what sorts of analysis you can do (which we'll cover in more detail in the next section), here are some examples using the (simple) MIDI sequence we just constructed.\n", "\n", "#### Plotting a piano roll\n", "\n", "A great way to visualize MIDI data is via a piano roll, which is a time-frequency matrix where each row is a different MIDI pitch and each column is a different slice in time. `pretty_midi` can produce piano roll matrices for each indivual instrument (via `Instrument.get_piano_roll`) or the entire `PrettyMIDI` object (summed across instruments, via `PrettyMIDI.get_piano_roll`). The spacing in time between subsequent columns of the matrix is determined by the `fs` parameter." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAfoAAAEKCAYAAAD6h5dQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4wLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvqOYd8AAAGR5JREFUeJzt3XuwZWV55/Hvr680QaJGUIlgK4yDIyAC4hDl5iWOFCAaMFI4EzMaSzNMvIGQVGLIQDJjFDURR+Jg1Fgqf+Cg4C1aDglS6oBQNA04WgQkEggKmRpotC+n+5k/1tq4z/Hcuul91t7rfD9Vp96z3vWutZ7eu+A571p7v0+qCkmS1E8rug5AkiSNjolekqQeM9FLktRjJnpJknrMRC9JUo+Z6CVJ6jETvSRJPWailySpx0z0kiT12KquA9gdkri8nyRpOXmgqvZZzMBeJPpGj/4pkiTNa+ruxY701r0kST1mopckqcdM9JIk9ZiJXpKkHjPRS5LUYyZ6SZJ6zEQvSVKPmeglSeqxsUj0SU5LUkkOntG/d5J7klzSVWySJE2ysUj0wJnAdW077ELg2qUPR5Kkfug80SfZC3gR8AbgtUP9RwJPBr7WUWiSJE28zhM98Ergq1X1A+DBJEcmWQFcDJzTbWiSJE22cagEcybwF+3vl7fbxwBfrqp7ksx5YJJTgFNGHqEkSRMqVd1VeE3yROAe4CdAASvb9pvAscAOYC9gDfDfq+r8Oc5T4/E3iyRJS2Hqxqo6ajEju751fzrwqap6elWtr6r9gbuAv6qqA6pqPc3t+7+ZK8lLkqS5dZ3ozwSunNH3OX7x0/eSJGkXdHrrfnfx1r0kaXmZnFv3kiRphEz0kiT1mIlekqQeM9FLktRjJnpJknrMRC9JUo+Z6CVJ6rGRJvokT07ymSR3JrkxybeTvGrGmGuS7JHkg0mOmeUcVyW5dZRxSpLUVyNL9Gmq0XweuLaqnllVR9KUoX3a0Jh1wI6q2gw8H/jujHO8Gtg0qhglSeq7Uc7oXwxsrapLBx1VdXdVfQiamTywETgkyUbgUOCGJCe1+/cC3gFcNMIYJUnqtVGuG/sc4Ka5dlbViUnOBe4EHgBOrqpzh4ZcSFOT/qcjjFGSpF5bsg/jJflwkg1JbhjqPgLYABzWtoOxhwMHVtXMgjczz3lKko+OJGBJknpgZEVtkrwEeHdVHT/U9ySa5/AXAWcDBwF3AAcA9wM3VdVZSd4C/BGwleauw77At6rqhDmuZVEbSdIysviiNqNM9AG+A3yiqj7S9h1A8+G89Un2BS6rqlOTXF9VR89xnvXAF6vqkHmuZaKXJC0jY1C9rpq/IE4Djk9yV5LrgU8C57VDjgOuS7I/cPeo4pAkaTmzHr0kSRNnDGb0kiSpeyZ6SZJ6zEQvSVKPmeglSeoxE70kST1mopckqcc6TfQLlbFNckCSTUnO6TJOSZImVWeJfjFlbIH3A1/pIj5Jkvqgy1VmZi1jCwzK2J4G3AU80k14kiRNvi5v3c9ZxratRX8e8CdLGpEkST0zNuvGJvkw8CKainV/D3ygqjY1d/jnPOYU4JSliVCSpMnT2Vr3C5Sx/RGwf9v9eGBHO/aSOc7lWveSpGVkMta6/1/AHm3t+YE9Aarq2KpaX1XrgQ8CfzZXkpckSXPrLNEvooytJEl6jCxTK0nSxJmMW/eSJGnETPSSJPWYiV6SpB4z0UuS1GMmekmSesxEL0lSj5noJUnqsZEn+iTbk9w89LN+xv5rkuyR5INJjpnl+KuS3DrqOCVJ6qOlWGXmZ1V1+Gw7kqwDdlTV5iTPB86dsf/VwKYliFGSpF7q7NZ9kmuAjcAhSTYChwI3JDmp3b8X8A7goq5ilCRp0i3FjH5dkpvb3++qqlcBVNWJSc4F7gQeAE6uquEZ/YXAxcBPlyBGSZJ6qdNb98ARwJXAK4ANg84khwMHVtXbZz7TH2Y9ekmS5jfyojZJNlXVXjP63gicDRwE3AEcANwP3FRVZ7Wla/8I2Erzx8i+wLeq6oQ5rmFRG0nSMrL4ojadJPq2f1/gsqo6Ncn1VXX0HMevB75YVYfMcw0TvaSxkKxq29UArFixtmmzBoCVK5p21cp1Tbti0L+WVWnGDtrV2XP6drUtg+3m2LWP9q9qj1vZbjcfw1q9omnXtu2qFWn7p7eD/jXtp7dWD7WrMhhb7bloj5kxNjVt3OrmMNas2DG9/9H9g+0dM8bN3q5a2Y5buZ3VK7c3fauavpXtvsH2qjXN/pWrm2usWL2jbZne7tG0aYNN+wI82rb/uOzR5pk1K9v+le122z+8vXbNjH3txda07eq2f4/mvatf2L9m2nat3WPaeVate/lEVK87Drguyf7A3R3GIUlSb418GjzbbL7tv2Jo84x5jv8hMOdsXpIkzc2V8SRJ6jETvSRJPWailySpx0z0kiT1mIlekqQeM9FLktRjY5Ho5ytlm+SAJJuSnNNdhJIkTaZxWU5uvvXw3w98ZSmDkSSpL8Yl0c8qyWnAXcAjXcciSdIkGotb97SlbNufK+HRevTnAX/SbWiSJE2ucZnRz3br/gLgA1W1KW0xhZksUytJ0vzGJdHP5gXA6Un+HHg8sCPJ5qq6ZDCgqq4Grk7yO10FKUnSOBvbRF9Vxw5+T3IBsGk4yUuSpIWNbaKXtHOmtn+96xAEMDXVtNu2Ne3mzQBksL1ta9Nu3Ta9f/OWnx+zdTB2avr2lsH+qRn7m7a2/qztb+qw1+ap6dtbd7RtU5+9tjXtjs1t255+Rxvijm3NY9Pt28LUtqbW+vapFe0/c9A2/VPbm+2t21e2l2z372jabTParTvacTuaa2xuj3t4atW0/i1tO9ieqsE2bBv6vTkn08YO+qeqpo/bPhg3vX9qsN2O37p9R7s9s21OsI3m9d2S5gXbNmjZyrZsacdubvt+1sayub1Ws397bWm3t7avYzNue7u9Y9C242rw5uyEsUj0c5WyHdp/wRKFIklSr4zLp+4lSdIImOglSeoxE70kST1mopckqcdM9JIk9ZiJXpKkHjPRS5LUY50n+llq0Z8/Y/9fJtnUVXySJE2ycVgwZ85a9EmOAp6wxPFIktQbnc/o55JkJfBe4F1dxyJJ0qQah0S/bsat+99s+88Grqqq+7oMTpKkSTaWt+6T7AecAZww34HWo5ckaX7jMKOfzfOAg4A7kvwQ2DPJHTMHVdXVVfWmpQ5OkqRJkWrL8XUWQLJpoep1C41JUuNxc0LScpesatvVAKxYsbZpswaAlSuadtXKdU27YtC/llVpxg7a1dlz+na1LYPt5ti1j/avao9b2W43c7nVK5r2C//ynt3271TXpm6sqqMWM3IcsuO6JDcPbX+1qs6fc7QkSVq0zhN9Va1cxJh5Z/ySJGl24/qMXpIk7QYmekmSesxEL0lSjy0q0Sd5VpJvJLm13T4syR+ONjRJkvRYLXZG/z+A3we2AVTVLcBrRxWUJEnaPRab6Pesqutn9E3t7mAkSdLutdhE/0CSA4ECSHI6MO8a9EPlZ29LsiHJO5P8wvWSXJNkjyQfTHLMLPuvGjwykCRJO2ex36P/T8BHgYOT/BNwF3DWAsc8uoZ9kn2BzwB7A388GJBkHbCjqjYneT5w7vAJkrwasBa9JEm7aLEz+qqqlwL7AAdX1Yt24liq6sfAm4CzkwSamTywETgkyUbgUOCGJCe1+/cC3gFctNjrSJKk6RY7o/8ccERVPTLUdwVw5GIvVFV3tjXm9wXur6oTk5wL3Ak8AJxcVcMz+guBi4GfLvYakiRpunkTfZKDgecAv9zeRh/YG9hjN1z/COBK4BXAhqHrHg4cWFVvT7J+nvgsUytJ0jwWmtH/a+Bk4PFMT6gPA7+zMxdK8kxgO/DjJG8EzqYpRfts4ADg/iSvqKqzgGOAo9oStauAfZP8XVWdMHzOqroauDrJTsUiSdJyMW+ir6ovAF9IckxVfXtXL5JkH+BS4JJq6uJeluQq4LKqOjXJ9VV19NB1PwJ8pD12PfDFmUlekiQtbLHP6H+U5Erghe32N4G3VtU98xwzKD+7muY7958C3j+0/zjguiT7A3fvXNjqs6ntX+86BGnXTbVLjGzb1rSbNwOQwfa2rU27ddv0/s1bfn7M1sHYqenbWwb7p2bsb9ra+rO2f3uzvXlq2vaq8x7Dv0sTa7GJ/uM0X487o91+Xdv3srkOWKj8bFVdMbR5xjzjfggcssg4JUnSkMV+RW7fqvp4VU21P5+g+aqdJEkaYzuzMt7rkqxsf14HPDjKwCRJ0mO32ET/H4HXAP9Ms/Tt6cBvjyooSZK0eyzqGX1V3Q2cOuJYJEnSbrbQgjnvnmd3VdWFuzkeSZK0Gy00o39klr5fAt4A/ArNMrWSJGlMLbRgzsWD35M8DngrzbP5y2nWoZckSWNswQ/jJXlikouAW2j+MDiiqs5rK9I9JoupWZ/kgCSbkpzzWK8nSdJys9Az+vcCr6apRX9oVe3u2vAL1qynWU3vK7v5upIkLQsLzejfCewH/CFwb5KH2p+Hkzy0OwOZo2b9acBdwG2781qSJC0XCz2jX+z37HeL4Zr1SR4BzqNZZtfb9pIk7YLFrnXfhQuAD1TVpnaC/wusRy9J0vzGKtEP16wHXgCcnuTPgccDO5JsrqpLBuOtRy9J0vzGJtHPUrP+2KF9FwCbhpO8+mvVyjmLIkqSdlLXiX6hmvWSJOkxSDN5nmxJqvu/WSRJWipTN1bVUYsZuaSfqpckSUvLRC9JUo+Z6CVJ6jETvSRJPWailySpx0z0kiT1mIlekqQeG3miT/KUJJcn+YckNyb5cpJnDe3/bJJnJHlbkjNnOf4vk+zu8riSJC0LI030bbnZK4G/q6oDq+pI4PeBJw8NW19VdwHHA9fOOP4o4AmjjFGSpD4b9Yz+RGBbVV066KiqDVX1zSSfTnI7cHC7DO6vA19K8kaAtlzte4F3jThGSZJ6a9Trxh4C3Djbjqo6K8kZwAHAFcD7quqMoSFnA1dV1X2WqZUkadd0/WG8I4ANwGFtC0CS/YAzgA/Nd3BVXV1VbxpphJIkTbBRz+hvA06f2ZnkJODPgGcAJwP7AI8keUlVnQg8DzgIuKOdze+Z5I6qOmjE8UqS1CsjrV7XfhjvO8DHquqjbd9hwC8D3wKuraoXJvkG8KqqemiO82yqqr3muc5YVq+b2v71rkOQdtmqlS/rOgRJcxqT6nXV/BXxKuCl7dfrbgP+K/DPNLP2DUnWAKvnSvKSJGnXjXwaXFX3Aq+ZY/d32/a4Bc4x52xekiTNresP40mSpBEy0UuS1GMmekmSesxEL0lSj5noJUnqMRO9JEk91lmin698bZK9k9yT5JKu4pMkqQ86WU5uqHztJ6vqtW3fc2nK1/4AuJAZJWslSdLO62rd2FnL1wIkOZIm4X8VWNTyfpIkaXZd3bqftXxtkhXAxcA5Sx6RJEk9NG6VYH4X+HJV3TNXDfqBJG8CLFErSdI8ukr0s5avBY4Bjk3yu8BewJq2ct35Mwe21fAGFfFGV4JPkqQJNtIytXNedJ7ytVX1zXb79cBRVXX2Is43lmVqJUkajTEpUzuXBcrXSpKk3aSTGf3u5oxekrS8jPmMXpIkLQ0TvSRJPWailySpx0z0kiT1mIlekqQeM9FLktRjJnpJknqs00SfZHuSm5NsSHJTkl9r+5/ebt+c5LYkb+4yTkmSJlWnC+a069jv1f7+cuAPqur4JGva2LYk2Qu4Ffi1qrp3jvO4YI4kaRlZ/II545Qd9wb+L0BVbR3qX4uPGCRJ2iVdJ/p1SW4G9gCeCrx4sCPJ/sCXgIOAc2ebzSc5BThliWKVJGnijNOt+2OAy4BDaiioJPsBnwdOqar75ziPt+4lScvIBK51X1XfBp4E7DOj/16aZ/THdhGXJEmTbGwSfZKDgZXAg0melmRd2/8E4EXA97uMT5KkSdT1/e7BM3qAAL9VVduTPBu4uLklT4D3VdXGzqKUJGlCWY9ekqSJM4HP6CVJ0u5nopckqcdM9JIk9ZiJXpKkHjPRS5LUYyZ6SZJ6bOSJPslpSapdEGfmvs8meUaStyU5c6j/Y23p2luSXNFWsJMkSTtpKWb0ZwLXte1M66vqLuB44Nqh/rdX1XOr6jDgH4GzRx+mJEn9M9JE387EXwS8AXjtUP+nk9wOHNyujPfrwJeSvBGgqh5qxwVYB0z+qj6SJHVg1MvJvRL4alX9IMmDSY6sqhur6qwkZwAHAFfQLHF7xvCBST4OnATcDrxzxHFKktRLo751fyZwefv75Uy/fX8EsAE4rG2nqarfBvYDvgf85mwnT3JKko/uzoAlSeqTka11n+SJwD3AT2huva9s27cAfwo8g+b5+z7AI8A/VtWJs5znOOBdVXXyPNdyrXtJ0jIyHmvdnw58qqqeXlXrq2p/4C7gYeBI4NaqOhS4DXjeIMmncdDgd+BU4P+MME5JknprlNPgM4H3zOj7XNv/U2BDkjXA6sGH71oBPplk7/b3DTR3ASRJ0k6yTK0kSRNnPG7dS5KkjpnoJUnqMRO9JEk9ZqKXJKnHTPSSJPWYiV6SpB4z0UuS1GNjkehn1qxP8vQkNyW5OcltSd7cdYySJE2isUj0/GLN+vuAY6rqcOAFwPlJ9usqOEmSJlXniX62mvVVtbWqtrRD1jIGcUqSNInGIYE+WrMeeDDJkQBJ9k9yC/Aj4D1Vde/MAy1TK0nS/MYh0c9as76qflRVhwEHAb+V5MkzD6yqq6vqTUsWqSRJE6bTSjBtzfoXA4c2hWmamvVJzq222k5V3ZvkVuBY4IruopUkafJ0PaOfq2b9sUnWASR5As0z/O93GKckSROp69quc9Ws/ytgWzvLD/C+qtq41MFJkjTprEcvSdLEsR69JEnCRC9JUq+Z6CVJ6jETvSRJPWailySpx0z0kiT12EgTfZInJ/lMkjuT3Jjk20leNWPMNUn2SPLBJMcM9X81yYa2TO2lSVaOMlZJkvpoZIk+SYDPA9dW1TOr6kia6nRPGxqzDthRVZuB5wPfHTrFa6rqucAhwD7AGaOKVZKkvhrljP7FwNaqunTQUVV3V9WHoJnJAxuBQ5JsBA4FbkhyUjv2ofawVcAaYPJX9pEkaYmNcjm55wA3zbWzqk5Mci5wJ/AAcHJVnTs8JsnfAkcDX8GCNpIk7bQl+zBekg+3z9xvGOo+AtgAHNa201TVy4GnAmtp7hDMPKf16CVJmsfI1rpP8hLg3VV1/FDfk2iew18EnE1Ta/4O4ADgfuCmqjprlnP9B+Doqjp7jmu51r0kaRlZ/Fr3o0z0Ab4DfKKqPtL2HUDz4bz1SfYFLquqU5NcX1VHDx27F/C4qrovySrg08A3q+qSOa71MJax7dqTaB7BqFu+D93zPRgPfX8fnl5V+yxm4MimwVVVSU4DPpDkXcBPgEeA89ohxwHXJdkfuHvG4b8EXJVkLc3jhWuAS5nb9xf7l41GI8l3fQ+65/vQPd+D8eD78HMjvd9dVffRfKVutn3DH647Y8a++2m+bidJkh4DV8aTJKnH+pLo/eR993wPxoPvQ/d8D8aD70NrZB/GkyRJ3evLjF6SJM1iohN9kn+X5PtJ7khyftfxLAcLveZJXp/kJ0lubn/e2EWcy02Sv07y4yS3dh3LcrHQa57khCT/b+i/hXcvdYzLTZL920Jpt7cF0d7adUzjYGJv3bfV7H4AvAy4B7gBOLOqbu80sB5bzGue5PXAUXMtbqTRSHIcsAn4m6o6pOt4loOFXvMkJwDnVNXJSx3bcpXkqcBTq+qmJI8DbgROW+55YZJn9EcDd1TVnVW1FbgceGXHMfWdr/mYqqprgX/pOo7lxNd8/FTVfVV1U/v7w8D3gF/tNqruTXKi/1XgR0Pb9+AbOmqLfc1/I8ktSa5oF0SSlqtj2hofX0nynK6DWU6SrAeeB/zvbiPp3iQneo2nq4H1VXUY8HXgkx3HI3XlJpplSp8LfAj4fMfxLBvtMuqfA942VPJ82ZrkRP9PwPBs8Wltn0Znwde8qh6sqi3t5mXAkUsUmzRWquqhqtrU/v5lYHVb2EsjlGQ1TZL/dFX9z67jGQeTnOhvAP5VkmckWUOz1O5VHcfUdwu+5u2HYQZOpXlGJi07SZ7SFvciydE0/799sNuo+q19vT8GfK+q3t91PONiYmu7VtVUkrOBvwVWAn9dVbd1HFavzfWaJ/kvwHer6irg95KcCkzRfFDp9Z0FvIwk+SxwAvCkJPcAf1xVH+s2qn6b7TUHVgNU1aXA6cBbkkwBPwNeW5P6NafJ8ULg3wMbk9zc9v1Be0dl2ZrYr9dJkqSFTfKte0mStAATvSRJPWailySpx0z0kiT1mIlekqQem9iv10na/ZL8CvCNdvMpwHbgJ+32T6vq1zoJTNIu8+t1kmaV5AJgU1W9r+tYJO06b91LWpQkm9r2hCR/n+QLSe5M8t+SnJXk+iQbkxzYjtsnyeeS3ND+vLDbf4G0PJnoJe2K5wJvBp5NsxLZs6rqaJr6Bv+5HfMXwAeq6vnAb7T7JC0xn9FL2hU3VNV9AEn+Afha278ROLH9/aXAv2mXewfYO8leg0IvkpaGiV7Srtgy9PuOoe0d/Pz/KyuAf1tVm5cyMEnTeete0qh8jZ/fxifJ4R3GIi1bJnpJo/J7wFFJbklyO80zfUlLzK/XSZLUY87oJUnqMRO9JEk9ZqKXJKnHTPSSJPWYiV6SpB4z0UuS1GMmekmSesxEL0lSj/1/d1wlwnWUcxUAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "def plot_piano_roll(pm, start_pitch, end_pitch, fs=100):\n", " # Use librosa's specshow function for displaying the piano roll\n", " librosa.display.specshow(pm.get_piano_roll(fs)[start_pitch:end_pitch],\n", " hop_length=1, sr=fs, x_axis='time', y_axis='cqt_note',\n", " fmin=pretty_midi.note_number_to_hz(start_pitch))\n", "\n", "plt.figure(figsize=(8, 4))\n", "plot_piano_roll(pm, 56, 70)\n", "# Note the blurry section between 1.5s and 2.3s - that's the pitch bending up!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Sonification\n", "\n", "`pretty_midi` has two main ways to sonify MIDI data: the `synthesize` and `fluidsynth` functions. `synthesize` is a simple and rudimentary method which just synthesizes each note as a sine wave. `fluidsynth` uses the Fluidsynth program along with a SoundFont file (a simple one is installed alongside `pretty_midi`) to create a General MIDI synthesis. Note that you must have the Fluidsynth program installed to use the `fluidsynth` function. Both the `Instrument` and `PrettyMIDI` classes have these methods; the `PrettyMIDI` versions just sum up the syntheses for all of the contained instruments." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# Synthesis frequency\n", "fs = 16000\n", "IPython.display.Audio(pm.synthesize(fs=16000), rate=16000)\n", "# Sounds like sine waves..." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", " \n", " " ], "text/plain": [ "" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "IPython.display.Audio(pm.fluidsynth(fs=16000), rate=16000)\n", "# Sounds (kind of) like a cello!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Writing it out\n", "\n", "Finally, we can easily write out what we just made to a standard MIDI file via the `write` function. `pretty_midi` puts each `Instrument` on a separate track in the MIDI file. Note that because `pretty_midi` uses a slightly different representation of MIDI data (for example, representing time as absolute seconds rather than as ticks), the information written out to the file will be slightly different. Otherwise, everything in your `PrettyMIDI` object will be included in the generated MIDI file." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "pm.write('out.mid')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Parsing a MIDI file\n", "\n", "The other intended use of `pretty_midi` is to parse MIDI files, so that they can be manipulated and analyzed. Loading in a MIDI file is simple. `pretty_midi` should be able to handle all valid MIDI files, and will raise an Exception of the MIDI data is corrupt." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [], "source": [ "# We'll load in the example.mid file distributed with pretty_midi\n", "pm = pretty_midi.PrettyMIDI('example.mid')" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(12, 4))\n", "plot_piano_roll(pm, 24, 84)" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "There are 12 time signature changes\n", "There are 13 instruments\n", "Instrument 3 has 888 notes\n", "Instrument 4 has 26 pitch bends\n", "Instrument 5 has 169 control changes\n" ] } ], "source": [ "# Let's look at what's in this MIDI file\n", "print('There are {} time signature changes'.format(len(pm.time_signature_changes)))\n", "print('There are {} instruments'.format(len(pm.instruments)))\n", "print('Instrument 3 has {} notes'.format(len(pm.instruments[0].notes)))\n", "print('Instrument 4 has {} pitch bends'.format(len(pm.instruments[4].pitch_bends)))\n", "print('Instrument 5 has {} control changes'.format(len(pm.instruments[5].control_changes)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### A note on timing information\n", "\n", "As discussed above, `pretty_midi` stores the time of different events in absolute seconds. This is different from MIDI, where the timing of events is determined in terms of relative \"ticks\" from the previous event. The amount of time each tick corresponds to depends on the current tempo and the file's resolution. Naturally, this is a woefully difficult way to deal with timing, which is why `pretty_midi` represents time in terms of absolute seconds. Hoever, we don't want to totally get rid of the metrical grid, so `pretty_midi` retains a mapping between times and ticks which is based on tempo change events." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "24.271851000000005\n", "2688\n", "24.271851000000005\n" ] } ], "source": [ "# What's the start time of the 10th note on the 3rd instrument?\n", "print(pm.instruments[2].notes[10].start)\n", "# What's that in ticks?\n", "tick = pm.time_to_tick(pm.instruments[2].notes[10].start)\n", "print(tick)\n", "# Note we can also go in the opposite direction\n", "print(pm.tick_to_time(int(tick)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Modifying the MIDI data\n", "\n", "Anything we did above when creating a MIDI file can now be done to the parsed MIDI object. For example, we can add or remove notes from instruments, add or remove instruments from the MIDI sequence, or even modify the attributes of individual events." ] }, { "cell_type": "code", "execution_count": 22, "metadata": {}, "outputs": [], "source": [ "# Let's shift the entire piece up by 2 semitones.\n", "for instrument in pm.instruments:\n", " # Skip drum instruments - their notes aren't pitched!\n", " if instrument.is_drum:\n", " continue\n", " for note in instrument.notes:\n", " note.pitch += 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Adjusting timing\n", "\n", "There are two ways to modify the timing of a MIDI sequence in `pretty_midi`. The first way is to directly changing the timing attributes of all of the events in the `PrettyMIDI` object (and its `Instrument`s). While simple, the issue with this approach is that the timing of these events will no longer match the metrical information in the MIDI file. The second approach is to use the `adjust_times` function, which effectively takes an original and adjusted temporal grid and correctly performs the warping - ensuring that the timing/metrical information remains correct. This can also be used for cropping out portions of the MIDI file." ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "26.699036100000004\n" ] } ], "source": [ "# Get the length of the MIDI file\n", "length = pm.get_end_time()\n", "# This will effectively slow it down to 110% of its original length\n", "pm.adjust_times([0, length], [0, length*1.1])\n", "# Let's check what time our tick from above got mapped to - should be 1.1x\n", "print(pm.tick_to_time(tick))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Analyzing the MIDI data\n", "\n", "`pretty_midi` contains extensive functionality for deriving information from a MIDI sequence. Much of this information is not readibly accessible from the MIDI file itself, so a primary goal of `pretty_midi` is to take care of all of the parsing and analysis in a correct, efficient, and easy-to-use way.\n", "\n", "#### Timing information\n", "\n", "Inferring, for example, the beat or downbeat times from a MIDI file requires keeping careful track of tempo change and time signature change events. `pretty_midi` handles this for you, and keeps them correct when you use `adjust_times`." ] }, { "cell_type": "code", "execution_count": 24, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAEKCAYAAAAMzhLIAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4wLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvqOYd8AAAIABJREFUeJzt3Xt0nHW97/H3N0lTKBQa0lgKaVMCtUq7t9gUDOCWmyIg23JApchBtoJFRbeX7VFRd0XWYS/1eMMlW6zQDXhKC4oKmyNbFLnolpQ2yCUFKyWQklLaNA3lUmku8z1/zDPtdDozeZJmnmcmz+e1Vlbm95tnkm+erMw3v7u5OyIiIoVUxR2AiIiUNyUKEREpSolCRESKUqIQEZGilChERKQoJQoRESlKiUJERIpSohARkaKUKEREpKiauAPYF1OnTvVZs2bFHYaISEVpb2/f6u4NYa+v6EQxa9Ys1qxZE3cYIiIVxcy6RnK9up5ERKQoJQoRESlKiUJERIpSohARkaKUKEREpCglChERKUqJQkTGXHtXH9fet572rr64Q5ExUNHrKESk/LR39XHh9W30D6aorali+aWttDTVxR2W7AO1KERkTLV19tI/mCLlMDCYoq2zN+6QZB8pUYjImGptrqe2popqgwk1VbQ218cdkuwjdT2JyJhqaapj+aWttHX20tpcr26ncUCJQkTGXEtTnRLEOKKuJxERKUqJQkREilKiEJFEuGXVBi66YRW3rNoQdygVR2MUIjLu3bJqA1/+5RMA/OHprQB88G0z4wypopSsRWFmy8xsi5l1ZNUdY2ZtZvaoma0xs+OCejOzH5jZejN73MzmlyouEUmeZf/9bNGyFFfKrqcbgTNy6r4FfN3djwGWBGWAM4HZwcdi4EcljEtEksa9eFmKKlmicPcHgW251cBBweODgReCxwuBmz2tDZhiZtNLFZuIJMs73zytaFmKi3qM4jPAb8zs26ST1AlB/eHA81nXdQd1m3K/gJktJt3qYOZM9TGKyPDaN/QVLUtxUc96+jjwWXefAXwWuGGkX8Ddl7r7Andf0NDQMOYBisj48/y2HUXLUlzUieJi4BfB458BxwWPNwIzsq5rDOpERPbZG6dN3qN86EH7xRRJZYo6UbwAnBQ8PhV4Onh8J/ChYPZTK7Dd3ffqdhIRGY3coevHurfrrIwRKOX02BXAQ8AcM+s2s0uAjwLfMbPHgH8jGGsAfg10AuuBnwCfKFVcIpI8Z87bc26MA7c/0h1PMBWoZIPZ7n5Bgada8lzrwOWlikVEku2Db5vJTx96jqdefGVX3dZXdsYXUIXRFh4ikgjzc3azbZg8MaZIKo8ShYgkwrnzG6mtqcKA2poqzp3fGHdIFUN7PYlIIrQ01bHiozpQaTSUKEQkMXSg0uio60lERIpSohCRxGjv6uPa+9ZrDcUIqetJRBKhvauPC69vo38wRW1NFcsvbVU3VEhqUYhIIrR19tI/mCLlMDCYoq2zN+6QKoYShYgkQmtzPbU1VVQbTKiporW5Pu6QKoa6nkQkEVqa6lh+qabHjoYShYgkxk8feo77/9rD05tfUaIYASUKEUmEz6z8M796NH2oZubz9xe9Nc6QKobGKEQkEe564oWiZSlMiUJEEsGwomUpTIlCRBLhPX83vWhZCivlwUXLzGyLmXXk1H/KzP5iZmvN7FtZ9VeY2XozW2dm7y5VXCKSTN9f9FbOOeYwpkyawDnHHKbxiREo5WD2jcAPgZszFWZ2CrAQeIu77zSzNwT1RwOLgLnAYcDvzOyN7j5UwvhEJGGUHEanZC0Kd38Q2JZT/XHgG+6+M7hmS1C/EFjp7jvd/VnSR6IeV6rYRCSZblm1gYtuWMUtqzbEHUpFiXp67BuBfzCzq4HXgc+7+2rgcKAt67ruoE5EZEzcsmoDX/7lEwD84emtQPqIVBle1IPZNcAhQCvwv4DbzGxEUw/MbLGZrTGzNT09PaWIUUTGoWV/7CxalsKiThTdwC887WEgBUwFNgIzsq5rDOr24u5L3X2Buy9oaGgoecAiMk7k/k86sv9REy3qRPEr4BQAM3sjUAtsBe4EFpnZRDM7ApgNPBxxbCIyjn3kxCOKlqWwko1RmNkK4GRgqpl1A18DlgHLgimz/cDF7u7AWjO7DXgSGAQu14wnERlLmfGIuzs2cea86RqfGIGSJQp3v6DAU/+zwPVXA1eXKh4RERkdbQooIomgWU+jpy08RCQR7u7YVLQshSlRiEgi1B9QW7QshSlRiEgi9L7WX7QshSlRiEginDlvetGyFKbBbBFJBE2PHT21KEREpCi1KEQkETQ9dvTUohCRRLh19YaiZSlMiUJEEmHaQfsVLUthShQikgiXnXQkNdXpHWNrqo3LTjoy5ogqh8YoRCQRWprquOq983bNemppqos7pIqhRCEiidDe1cdVd62lfzDF6ue2MefQyUoWIanrSUQSoa2zl50DKVIO/QMp2jp74w6pYihRiEgi1E2qxYPHKeCVvw3EGU5FUaIQkURY+8L2Pco/+eOztHf1xRRNZSlZojCzZWa2JTjNLve5fzEzN7OpQdnM7Admtt7MHjez+aWKS0SSyXPKqZSr+ymkUrYobgTOyK00sxnA6UD2apczSZ+TPRtYDPyohHGJSAKdN7+Rmqx3vOpqo7W5Pr6AKkjJEoW7Pwhsy/PU94AvsGeCXwjc7GltwBQz09aOIjJmWprquGrh31FlcUdSeSIdozCzhcBGd38s56nDgeezyt1BXb6vsdjM1pjZmp6enhJFKiLjUccL20kF/6IODjm3P9Idb0AVIrJEYWaTgC8DS/bl67j7Undf4O4LGhoaxiY4EUmE3MaEGhfhRNmiOBI4AnjMzJ4DGoFHzOxQYCMwI+vaxqBORGTMnDu/kdqaKgyorani3PmNcYdUESJbme3uTwBvyJSDZLHA3bea2Z3AJ81sJfA2YLu76+RzERlTLU11XPmPc7WNxwiVLFGY2QrgZGCqmXUDX3P3Gwpc/mvgLGA9sAP4cKniEolbe1cfbZ29tDbX640qYtrGY3RKlijc/YJhnp+V9diBy0sVi0i5aO/q48Lr2+gfTFFbU8XyS1v1RhWhzDYezu5tPHT/h6eV2SIRauvspX8wvd/QwKD2G4pa7jYedZNq4wynYihRiESotbme2poqqg0m1FRpwVfEOnK28cgtS37aZlwkQi1NdSy/tFVjFDHR9NjRUaIQiVhLU50SREzOnd/IytUbGEpBdRWaHhuSup5EJDHWvfgKQ6n046FUuizDU6IQkcS4dfWGomXJT4lCRBJj2kH7FS1LfkoUIpIYl510JDXV6SHsmmrjspOOjDmiyqDBbBFJjJamOm5dfLxmnY2QWhQiIlKUWhQikhjtXX2c/+M/MZiCmiq49bIT1KoIQS0KEUmM6x54hsFgeuxgKl2W4SlRiEhiPJWzZUduWfJTohCRxPBhypKfEoWIJMbhU/YvWpb8SpYozGyZmW0xs46suv9jZn8xs8fN7JdmNiXruSvMbL2ZrTOzd5cqLhFJrtnTJhctS36lbFHcCJyRU/dbYJ67/z3wV+AKADM7GlgEzA1e8+9mVl3C2EQkgc6d37jHgjttChhOqERhZnPN7GPBx9wwr3H3B4FtOXX3uPtgUGwDMr+lhcBKd9/p7s+SPhL1uFA/gYjICKQP1Nz9WYY3bKIws08CPwNmBh+3mdknxuB7fwS4O3h8OPB81nPdQZ2IyJi57oFn9tg9VtNjwwmz4G4xcJy7vwpgZv8G/An499F+UzP7CjAILB/FaxcHMTFz5szRhiAiCfTs1teKliW/MF1PBvRnlQfYh4OhzOyfgLOBC313228jMCPrssagbi/uvtTdF7j7goaGhtGGISIJ1Dz1gKJlyS9MovgpsMrMvmpm/0q6NXHTaL6ZmZ0BfAF4r7vvyHrqTmCRmU00syOA2cDDo/keIiKFnDznDUXLkt+wXU/u/i0zux94O+n1KR9z99XDvc7MVgAnA1PNrBv4GulZThOB35oZQJu7f8zd15rZbcCTpLukLnf3odH9SCIi+fXt6KfKIOVQZemyDC/spoCvAzuBVPB5WO5+QZ7qG4pcfzVwdch4RERGrLW5npoqY2DIqakyWpvr4w6pIoSZ9fQVYAUwnfTYwS1mdkWpAxMRKQmzPT/LsMKMUXwIONbdv+ruXyG9vuGfShqViEgJtHX2MjiUwoGhoRRtnb1xh1QRwiSKTezZRVUT1ImIVJTW5npqa6qoNphQU6Wup5DCjFFsA9aa2W9ID2afDqw2s+8CuPvnShifiMiYaWmqY8nZc7m7YxNnzpuuQ4tCCpMo/l/wkdFWolhEREqqvauPq+5aS/9gitXPbWPOoZOVLEIIMz224EwlEZFK0tbZS/9gipTDwGB6jEKJYnhhZj2dYWargy3Dt5lZn5ltG+51IiLlJjM91oBqTY8NLUzX0w+BDwBPkF5HISJSucwA1/TYEQgz66kbeNTdB9x9KPNR6sBERMaapseOTpgWxReA/wy28di1Ktvdf1CqoERESiEzPXZgMKXpsSMQJlF8nfSOsVNQ15OIVLCWpjqWX9pKW2cvrc31GsgOKUyimOHu80oeiYhIBFqa6pQgRijMGMVvzOzUkkciIhKB9q4+rr1vPe1dfXGHUjHCtCg+AnzWzHaQPsDIAHf3Q0oamYjIGGvv6uOCpQ8xMORMqDZWLD5erYsQwrQopgITgIOBhqCso+VEpOLc/kg3/UOOA/1Dzu2PdMcdUkUYNlEEU2HfD3wxeDwdOGa415nZsmCRXkdW3SFm9lszezr4XBfUm5n9wMzWm9njZjZ/9D+SiEh+W1/ZWbQs+YVZmf1D4BTgoqBqB3BdiK99I3BGTt2XgHvdfTZwb1AGOJP08aezgcXAj0J8fRGREWmYPLFoWfIL0/V0grtfRvqUO9x9G1A73Ivc/UHSO89mW8ju87ZvAs7Jqr/Z09qAKWY2PURsIiKhzT3s4KJlyS9MohgwsyrSW4xjZvWMfj3FNHfPnGXxIjAteHw48HzWdd1BnYjImMmcmQ06M3skCiYKM8vMiLoWuB1oMLOvA38Evrmv39jdnSD5jISZLTazNWa2pqenZ1/DEJEEaW2u35UoAOomDds5IhRvUTwM4O43A18Fvg30Ae9395Wj/H6bM11KwectQf1GYEbWdY1B3V7cfam7L3D3BQ0NmnwlIuGte/EVBoP+kJTDv97RofUUIRRLFLvyrruvdfdr3P377t5R5DXDuRO4OHh8MXBHVv2HgtlPrcD2rC4qEZExcevqDXuUh1LOLzRFdljFFtw1mFnBY07d/bvFvrCZrQBOBqaaWTfwNeAbwG1mdgnQRXr7coBfA2cB60nPqvpw2B9ARCSsaQftB2zfo27E/d8JVCxRVAMHktWyGAl3v6DAU6fludaBy0fzfUREwrrspCO59y+bGQq6n2qqjfPmN8YbVAUolig2uftVkUUiIlJiLU113HbZCVz3wDNsefl1zj92prbwCKFYotDxTyIyLv3h6R76B1Os27yWOYdOVrIYRrHB7L26iEREKl1bZy/9gylSDgODOuUujIKJIliBLSIyrmROuas2dMpdSGG2GRcRGTdamupYcvZc7u7YxJnzpqvbKQQlChFJlPauPq66ay39gylWP7dNYxQhhNnrSURk3NAYxcgpUYhIomiMYuTU9SQiiaIxipFTohCRRNEYxcip60lEEkVjFCOnFoWIJErmTIqUgxmxjlG0d/XR1tlL3aRa+nb009pcX5atGyUKEUmU7DMpBlPpchxvzu1dfZy/9CEGh3bvXzuh2li5+PiySxbqehKRRFn2x86i5aj8+IFn9kgSAANDzo8feCaWeIpRohCRZDErXo5I59bX8tav3fRyxJEMT4kihPauPq69b72OTBQZB975pjcULUelbtKEvPWv7hyIOJLhxTJGYWafBS4lfbjUE6RPtJsOrATqgXbgInfvjyO+bO1dfVx4fRv9gylqa6pYfmlr2fUfikh4k/efgJF+87GgHIe6SbV563f2pyKOZHiRtyjM7HDgn4EF7j6P9El6i4BvAt9z96OAPuCSqGPLR1PpRMaX1uZ6Jk5Ir8yeOCG+ldlTJ0/MW79zMFV2vRdxdT3VAPubWQ0wCdgEnAr8PHj+JuCcmGLbg5b7i4wvmZXZJxw1lSVnz42th6DQEawOZfcPaeRdT+6+0cy+DWwA/gbcQ7qr6SV3Hwwu6wYOjzq2fFqa6lh+aSttnb1lO8dZRMIrp5XZ1QY5E5+Awt1ScYk8UZhZHbAQOAJ4CfgZcMYIXr8YWAwwc+bMUoS4l5amOiUIkXGirbOXnQMpHOgfSHcnx/H33dbZS54cAUDHC9sjjWU4cQxmvxN41t17AMzsF8CJwBQzqwlaFY3AxnwvdvelwFKABQsWFLrPIiJ51U2q3fUGnSL6/94zq7Ff+dsAqQLvYFtf2RlpTMOJI1FsAFrNbBLprqfTgDXAfcD7SM98uhi4I4bYRGScu2/dlr3KH3xbNL0T+VZj59O59TXau/rKpicj8sFsd19FetD6EdJTY6tItxC+CHzOzNaTniJ7Q9Sxicj492TOgrbccinlW42dz/otr7Jo6UNlM/splllP7v41d3+Tu89z94vcfae7d7r7ce5+lLu/393Lq+0lIuPC/hOqi5ZLafPLr4e+tpy289DKbBFJlDhXZh8/wun15bKdhxKFiCTKyzsHi5ZLqdD+TpNqq8m349T+NeXxFq1txkUkUXJnFEU5w+iR5/OPOezoH8pb/843TytlOKGVR7qSRNEmixKnhpytM3LLpZQqNB82jzj3ocqlRCGRymyy+J171nHh9W1KFhK5c+c3UltThQG1NVWcW2ArjVJ4x+yG0Nc65bNCW11PEql8myyWy1xxSYaWpjpWfDSebXkmTRzZW27fjtg30AaUKCRidZNqqbL0Js/aZFHiEte2PCM9IqlcWhTqepLIZDZjG0o5VWax7twpyRbXONncww4e0fVry2TPJ7UoJDKZbicH3L1smtWSLHEeRta3o3/XoUlhPL35lVKGE5paFCEV+g9EM3jCyz3bo25Sre6dRC6ze2zKd+8eG5XsQ5Nqq43Tj55GbZG1EjsHy+O0u0S2KDK7Nw43kJW5rm5S7a7967P/A9ExqSOTfbZHoXsqUmpx7x77D7Mb2PLy6xzfXM/k/SfQPPUAfvfUZtb37L0Y7/xjo9mscDiJSxRh39yzr6syI+W+10wdzeAZucwg4rX3rde9k1jknvUQ1dkP7V19XLD0IfqDTQEf6979ffMNck89sDayXW2Hk7iup7BnYGdflwoGX3OPQ9UxqaOXmf1UpXsnEct9Ux7pTKTRauvsZaDAzrH5avcLuqTKoXs7cS2KzJv7wGCq6BtU7nVLzp5L347+PbqrdEzq6GTPfqqu0uwnida58xv5WXv3rr/tqBbctTbXU10FYYcdJu83oWy6txOXKMK+uSsJlE72UZSplGY/SbRamuq48h/ncnfHJs6cNz3Sv+1pB+3Hxpf23mr8qDccyPYd/fS8uvtvobamao+/ldcHUtz+SPeu8dEo35tiSRRmNgW4HphHutX1EWAdcCswC3gO+IC7l6StFXaxzXDX3bJqA0vu6CDlrgHZEYh7MFGSrb2rjyvv7GBgyFnV2cucQyeX/O+2vauP83/8p4Ktic6eV6nK6QM7/9iZbOh9bY9uqRWrNjDvsIMjnwgS1xjFNcB/ufubgLcATwFfAu5199nAvUG5bLV39bHkjg4GU+lB7v4i4x2yp74d/bv+KKqsfLYpkGS4/ZFu+occB/qHnNsf6S7592zr7C3a5ZRycId3HT2NoxoO4OBJNXz7nnXc9fgLe1znwLL/fjbUOOtYijxRmNnBwDsIjjp19353fwlYCNwUXHYTcE7UsY1EW2cvQ1k7QVaZaUA2pOxJALUayJaIxbHNeGtz/d6D6Lb7DTgzqePIqQewvuc1tu8YZNtr/XTn6aZ6aUd/5JNo4uh6OgLoAf7DzN4CtAOfBqa5+6bgmheB8tiIvYDMwpn+gRRVVcZVC+ep2ykkjf9IUmSPJbzr6Gnc8+TmXc+9683TeMuMKdRNqt01Ueaq/1w77NccHEpF/vcTR6KoAeYDn3L3VWZ2DTndTO7uZpZ3HpmZLQYWA8ycGd8cY73Z7Zu4NmUTieo8itwZS0vOnsv9f+3ZNdvqspOO3OtvYNpB+wHF13W89Lf0iXyXn3JUSeLOJ44xim6g291XBeWfk04cm81sOkDweUu+F7v7Undf4O4LGhrC7+1eCi1NdVx+ylF6wxOpILkb8410o76wctds9e3oZ8VHW/n8u+ew4qP5B6AvO+nIUF/7ugeeGetwi4o8Ubj7i8DzZjYnqDoNeBK4E7g4qLsYuCPq2EajHBbDiEh4mY35IP0GWKrJFPkW5A73z2VLUx0XhliNveXlvccuSimudRSfApabWS3QCXyY9O/sNjO7BOgCPhBTbKGVy2IYEQkvM7443KLbfTXa7ukwLZzjI54AEkuicPdHgQV5njot6lj2hfZ6Eqk8UY4vjmYsLkwLZ9mfnuNdcw+N7P0mcSuzx1LY7UBEpLyU82SKzFTaYmdW9Ef8j6kSxT7QzCcRGWstTXUc1XAAT+fZdjxblDsaKFHso3L+z0REKtNAavgz8KLc0SBx24yLiJS7Y2ZMGfaaKFsUShQiImWkvauP/1r74q6yAcc0HszpR++5WUVUBy6BEoWISFnJzKYEqDb4/Lvn8KtPvn2vFeRRHbgEShQiImWl0MmZUa0oz0eD2SIiZaTQbMrM9vwpj357fiUKEZEyk282ZZzrtpQoREQqQJzrtpQoQor6jFoRkVxxrdtSoiggOzEA2vxPRBJLiSKP3F1hz5vfqM3/RCSxND02j9xdYR0iP6NWRCRXXOffqEWRR+7sgvPmN3Le/EaNUYhIbOI8/0aJIo9CswuUIEQkLnGefxNbojCzamANsNHdzzazI4CVQD3QDlzk7tGtKMmhXWFFpJzEuY4izjGKTwNPZZW/CXzP3Y8C+oBLYolKRKQMZXo6Pnf6nMhnXsaSKMysEXgPcH1QNuBU4OfBJTcB58QRm4hIuWppquPyU46KvLcjrhbF94EvAKmgXA+85O6DQbkbODzfC81ssZmtMbM1PT09pY9URCThIk8UZnY2sMXd20fzendf6u4L3H1BQ0PDGEcnIiK54hjMPhF4r5mdBewHHARcA0wxs5qgVdEIbIwhNhERyRF5i8Ldr3D3RnefBSwCfu/uFwL3Ae8LLrsYuCPq2LLFtbBFRMafSn8/Kad1FF8EVprZ/wb+DNwQVyC5C1uWnD2Xvh39WmwnIqFl9ourm1TLVXetrei94mJNFO5+P3B/8LgTOC7OeDKyF7b0D6RYckcHKfeK/SWLSLSy/9msMiPlXtF7xWmvpzyyjyKsqtr7lywiUkz2P5uplFNlVtF7xZVT11PZyN7CI9NsjGM1pIhUptxV1JXefa1EUUD2Fh5zDp2cd0NAHWYkIvnEeRpdKShRhJBv36c4d3IUkfI3nvaL0xjFKOXbyVFEZDxSohil7AFvjV2IyHimrqdRGm99kCIihShR7IPx1AcpIlKIup5ERCqEzswWEZGC4pxpqRaFiEgFiHOmpRKFiEgFiHOmpbqeREQqQJwzLZUoREQqRFwzLdX1JCIiRcVxZvYMM7vPzJ40s7Vm9umg/hAz+62ZPR181gIFEZEyEEeLYhD4F3c/GmgFLjezo4EvAfe6+2zg3qAsIiIxi+PM7E3u/kjw+BXgKeBwYCFwU3DZTcA5UccmIiJ7i3WMwsxmAW8FVgHT3H1T8NSLwLSYwhIRkSyxJQozOxC4HfiMu7+c/Zy7O+AFXrfYzNaY2Zqenp4IIhURSTZLvydH/E3NJgB3Ab9x9+8GdeuAk919k5lNB+539znDfJ0eoGuUYUwFto7ytVEo5/jKOTYo7/jKOTYo7/gU2+jlxtfk7g1hXxz5OgozM+AG4KlMkgjcCVwMfCP4fMdwX2skP2ieONa4+4LRvr7Uyjm+co4Nyju+co4Nyjs+xTZ6+xpfHAvuTgQuAp4ws0eDui+TThC3mdklpFsJH4ghNhERyRF5onD3PwJW4OnTooxFRESGl+SV2UvjDmAY5RxfOccG5R1fOccG5R2fYhu9fYovlsFsERGpHEluUYiISAiJTBRmdoaZrTOz9WYW+1YhZvacmT1hZo+a2ZqgLra9r8xsmZltMbOOrLq88VjaD4J7+biZzY8htivNbGNw/x41s7OynrsiiG2dmb27xLGNaB+zGO5dofhiv39mtp+ZPWxmjwWxfT2oP8LMVgUx3GpmtUH9xKC8Pnh+VqliGya+G83s2ax7d0xQH+nvNvie1Wb2ZzO7KyiP3b1z90R9ANXAM0AzUAs8Bhwdc0zPAVNz6r4FfCl4/CXgmxHG8w5gPtAxXDzAWcDdpCcotAKrYojtSuDzea49Ovj9TgSOCH7v1SWMbTowP3g8GfhrEEO53LtC8cV+/4J7cGDweALp3RpagduARUH9dcDHg8efAK4LHi8Cbi3xvSsU343A+/JcH+nvNvienwNuAe4KymN275LYojgOWO/une7eD6wkvc9UuYlt7yt3fxDYFjKehcDNntYGTLH0gskoYytkIbDS3Xe6+7PAetK//1LFNtJ9zKK+d4XiKySy+xfcg1eD4oTgw4FTgZ8H9bn3LnNPfw6cZmaFZlOWMr5CIv3dmlkj8B7g+qBsjOG9S2KiOBx4PqvcTfE/lig4cI+ZtZvZ4qCu3Pa+KhRPudzPTwZN/GVZ3XSxxWbh9jErl/igDO5f0HXyKLAF+C3pFsxL7j6Y5/vvii14fjtQ0rNBc+Nz98y9uzq4d98zs4m58eWJvRS+D3wBSAXlesbw3iUxUZSjt7v7fOBM0tuuvyP7SU+3Ectmelq5xQP8CDgSOAbYBHwnzmBslPuYRSVPfGVx/9x9yN2PARpJt1zeFEccheTGZ2bzgCtIx3kscAjwxajjMrOzgS3u3l6q75HERLERmJFVbgzqYuPuG4PPW4Bfkv4j2Zxpqgaft8QXIRSJJ/b76e6bgz/iFPATdnePRB6bpfcxux1Y7u6/CKrh92HsAAACvUlEQVTL5t7li6+c7l8Qz0vAfcDxpLtsMguDs7//rtiC5w8GeksdW058ZwTdee7uO4H/IJ57dyLwXjN7jnRX+qnANYzhvUtiolgNzA5mBNSSHsy5M65gzOwAM5uceQycDnSwe+8rCLn3VYkViudO4EPBLI9WYHtWN0skcvp+/wfp+5eJbVEwy+MIYDbwcAnjGG4fM4jx3hWKrxzun5k1mNmU4PH+wLtIj6HcB7wvuCz33mXu6fuA3wettZIoEN9fsv4BMNJjANn3LpLfrbtf4e6N7j6L9PvZ7939Qsby3pV6JL4cP0jPSPgr6T7Qr8QcSzPpmSWPAWsz8ZDuM7wXeBr4HXBIhDGtIN0FMUC6b/OSQvGQntVxbXAvnwAWxBDbT4Pv/XjwRzA96/qvBLGtA84scWxvJ92t9DjwaPBxVhndu0LxxX7/gL8H/hzE0AEsyfr7eJj0QPrPgIlB/X5BeX3wfHOJ712h+H4f3LsO4P+ye2ZUpL/brDhPZvespzG7d1qZLSIiRSWx60lEREZAiUJERIpSohARkaKUKEREpCglChERKSqOo1BFKo6ZZaa4AhwKDAE9QXmHu58QS2AiEdD0WJERMrMrgVfd/dtxxyISBXU9iewjM3s1+HyymT1gZneYWaeZfcPMLgzOMXjCzI4Mrmsws9vNbHXwcWK8P4FIcUoUImPrLcDHgDcDFwFvdPfjSG///KngmmuA77n7scB5wXMiZUtjFCJja7UHe/qY2TPAPUH9E8ApweN3AkdnHQFwkJkd6LvPOxApK0oUImNrZ9bjVFY5xe6/tyqg1d1fjzIwkdFS15NI9O5hdzcUFpyzLFKulChEovfPwILgVLQnSY9piJQtTY8VEZGi1KIQEZGilChERKQoJQoRESlKiUJERIpSohARkaKUKEREpCglChERKUqJQkREivr/cvr92YlrT+QAAAAASUVORK5CYII=\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot the tempo changes over time\n", "# Many MIDI files won't have more than one tempo change event,\n", "# but this particular file was transcribed to somewhat closely match the original song.\n", "times, tempo_changes = pm.get_tempo_changes()\n", "plt.plot(times, tempo_changes, '.')\n", "plt.xlabel('Time')\n", "plt.ylabel('Tempo');" ] }, { "cell_type": "code", "execution_count": 25, "metadata": {}, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtQAAAEKCAYAAAAy8cIyAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4wLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvqOYd8AAAIABJREFUeJzt3XucFPWZ7/HvA4PcmRnkfh3UxWhQNBpfGkIEgibGy+oej+tZ9ZhsXqIbL8mJyUYTIuslq4lB3WgMYm6sR4/JmnUVY4wol7gmhoVERGSNoiiCBi8zyD2MPOePrh4G6Jnp7uqq+s305/16zcuu6qp6ft1dUzzWPP38zN0FAAAAoDzdsh4AAAAA0JmRUAMAAAAxkFADAAAAMZBQAwAAADGQUAMAAAAxkFADAAAAMZBQAwAAADEkmlCb2TAzu9/M1pjZcjN71MzGm9kYM3vczFab2Qtm1pDkOAAAAICkWFITu5iZSfqtpHnuPidaN1HSAEnXS/qWuy8ws36Sdrv7tkQGAgAAACSoJsFjT5W0K59MS5K7rzCzwyXVuPuCaN2Wjg40aNAgb2hoSGygeZs3b5Yk9e/fP/FYIcTNUrW913zGxO2KqvG9rrbPmc+46+Mz3t/y5cvfcffBpRwzyYR6gqTlBdaPl9RkZv8uaZykJyRd5e4ftHWghoYGLVu2LJlRtrJ48WJJ0pQpUxKPFULcLFXbe81nTNyuqBrf62r7nPmMuz4+4/2Z2WulHjPJhLq9mJMlHS3pdUk/k/RZST9qvZGZzZA0Y89yj8QHNmvWTEnS1KknJR4rhLiS5L5LUjrvb2vV9l7zGRM3SXzGXT82n3HXj81n3LljJ/mlxFWSjimw/g1Jz7r7K+7eLOk/JH1k343cfa67H+vuxyY4RgAAACCWJBPqhZJ6RneaJUlmdqSknpLqzCxfmzJN0gsJjgMAAABITGIJtefah5wlaXrUNm+VpBslbZD0FUlPmtlKSSbp7kLHMLPTzWxuUmMEAAAA4kq0htrdN0g6p8BTL0k6soj950uab2YXVXpsAAAAQCUwUyIAAAAQAwk1AAAAEEMWbfOKZmanSzo963EAAAAAbQn6DrW7z3f3GR1vCQAAAGQj6IQaAAAACB0JNQAAABADNdQAAABADEHfoaaGGgAAAKELOqEGAAAAQkfJBwAAABBD0HeoKfkAAABA6IJOqAEAAIDQkVADAAAAMVBDDQAAAMQQ9B1qaqgBAAAQuqATagAAACB0lHwAAAAAMQSdULv7fEnzzeyirMcCoDqcVHdlWfvV14yOtT8AoPOi5AMAAACIgYQaAAAAiCHokg9qqAEAABC6oBNqaqgBpG1B0+yy9vtY88xY+8dzUwYxq1NdzShJ0om1V2Q8EgAhoeQDAAAAiIGEGgAAAIgh6JIPaqgBAAAQuqATamqoAQAhaWp+Q5K0ZNP3Uo6cRW0+gGJR8gEAAADEEPQdako+AAAAELqgE2pKPgCUKt/WbErtl6oiLgAge5R8AAAAADGQUAMAAAAxBF3yQQ01AAAAQhd0Qk0NNYBS5duaLd50W6pxT4ymHk87bs7NGcQEUCnH113S8viqg77Z7rYPNb641/LUvoeWFGvR1r3371MzRJJ0WP05JR0nrqziFhN7deN9JR+Tkg8AAAAghkTvUJvZMEm3SfqopCZJf5b0JUmrJa2MNnvd3c9oY39KPgAAABC0xBJqMzNJD0qa5+7nRusmShoqabu7H9XRMSj5AHKOq7s4iGOUYkDNiLLjnnzg0JK2f/zdP1ckbhwDakbowAN66Prx7f+5tlQPbXyr6G2/cfA1FY3dkbG9x1Qs7mPvri962/41wyVJx9R9vqxYZwweUdZ+v3r7bTX0bpAkXXNIuu81urZnmuZIul2SdNMr15e07+rG8uNOqD9PJlNt9176RJ/x5R+ogAXbnm33edcHkqSd2lbRuO05qU8u9azv3luSNK1f4XKZct7TJO9QT5W0y93n5Fe4+wpJyuXaAAAAQOeXZA31BEnL23iul5ktM7NnzOzMBMcAAAAAJCqrLh9j3X29mR0kaaGZrXT3Na03MLMZkmZkMzwAAACgOEkm1KsknV3oCXdfH/33FTNbLOloSWv22WaupLmSZGae4DiB4C1tuivG3ndU4BilOyVqI1dO3KVN2cSN45TmmXq/Wbr2TzekGjfnTknSt9Zcl2rUWdtnRnHTfc2nNedqqJc3/ais/ZfHOL8+Fb3m615O9zVfq8rW5qfh2Lryv/6Ur5OPc4zOGDttzzfeq63N47S1WbprfbrntNlJqu3WR9N6t/+VusU7Vu63bmqvI4qKsWiffZ/cnlset3uQJOnXW58r6jjFSLLkY6GkntGdZkmSmR1pZpPNrGe0PEjSJEkvJDgOAAAAIDGJJdTu7pLOkjTdzNaY2SpJN0Yxl5nZCkmLJN3k7iTUAAAA6JQSraF29w2SCk1DU9S9evpQo5ByW2VJ8dttFVLun52RjKz+XFtNfyYGirGs6e6y9z01Kt2Kc4zOF/vOlONla9uut7VN0g83lF5q8rIeihV7+65cGvrye/GO01rQMyW6+3x354uJAAAACFbQCTUAAAAQuqza5hWFkg8AAACELuiEOu2px+trRkuSptd+OY1wmcd9YtMtqcZrrdha5kL1yXFqluO228pKJabRvvmwdNtuDeubm5b6tsOTj3vfho0tj025mVi7pfwHOJNpSM8eOn/EsIod8+H1W0raftX0fyhp+5+tHSxJ+tuGt0veR5Iaeo/R4F5/6TDuA68NKrj+7w7aM2X81r/0KHoM6+pGSpKenXppUdvf/9rAlsfnjn1P3buV34l13cDctOUvfSp+NeJ9rwyNfYyk9ayp04Hda3XJqI5/jx/Z8tRey280LU5oVOE5uv5zHW7zx8afpDASZIWSDwAAACAGEmoAAAAghqBLPqihBgAAQOiCTqjTrqFubF4nKf3a4klRz8ssa5rTtrn5TUmdr5Y5K5WYevyrq6+vzGCKNGtr7ry+9oV0p7PNfOrxlF9vznckSR9+4gdl7X3dy+VFnbV9ptZul04rM+6sl8qM+4ncZ3z6ou+XvO9Nr5QXsyX2x3OxP/PrufEOVKJrdE2q8fJ2NjdpQ3OT5ryRxXndeVSyPvqiETOL3vaJ7X/QyX0+UvT2j2/7w37retUcKEkaV/+Zoo9TCVnFLSb2q40Pl3xMSj4AAACAGIK+Q03JBwAAAEIXdEKdL/noUzPookMGnNGyfmXjPW3uc0T9BWXH61szNPYx0o67svEeHV5/bkn7vNB4/37rbjq0/ZZI899q3G/dJwcPLLBl+558+z1JUm1Nru3VpNrLSj7GGcPrS94nb1ifXCu3b3+o9FZuD7/ZqKmDSn/NkjS2dy7uzIMr+2fbRe+8V/S2k2ov09Ob7qhofADpumNC8eUAP1u3SZJ02vC6suMN6zNG7/6lWZNrLy95378eUX7cIdG1+sTaK0red9qQ2qK2W7hx017LpwzL7Tc8it3Rv4uS9Ku3NnW4TanuLnEq7rsaHy071oT689RdNarr3kun9D2m7OPsa8G25zvcxizX4rTGelYsbkem9f6wJGlg936S1Ga5zF2UfAAAAADpIqEGAAAAYgi65CNfQ31At/5ZDwUAAAAoKOiEunXbvPbqplsrdrtCtjaPjX2MLOIWqoku1VUvlt5S7ekYpWPTo9Zm5dT0xok7a1vUyu2/y2sBVW7sWdtzcW9Yk0XrqVsllfdeA8jesXV7Osde9nzp15CnKnDNfGrT7ZnEXbLpeyXvu6TMuPn9Wv6deDHt6/XslONJzzfeq63N47S1WbozxdaIE+rPUzfvrrruvfTpvhPa3faJLS/utTy176FFx1m0de99f7PtT5Kkgz4YstdyJVDyAQAAAMQQ9B1q2uYBAAAgdEEn1GnPlIj09K8ZLkk6pu7zRe9TzbMqTqy/MPYxvjqu9FaBvbtb2fEaolaB1xyS/AxvD737WsvjMb0bJElXH5TuzHJjotdb6biPNa4rettKt2XsSCXbQXoZcb+R8ut95L3XNLpXrkTvyobSf5/K1b/Hnt/DNH6fWkvz97hQ3GUntt2u7+H17bdQbX1dKEW/mmGSir/unlw3puhjP970+l7Lnxyw/75/N+Trbe6/6C9L9o7da0rRsSXp8R2L91t3QE3ULrBuUknHiuNdX6tdOkpvf7BDD2xeWNK+D25ZHzt+s3ZKkpo8/rHyKPkAAAAAYiChBgAAAGIIuuSDGmoAAACELuiEOl9DParXyIsubbh4v+d/WWA67KympY5Ratoyxep3Dys97iMbNuvkYaX16X78rc2SpMWbbmtZd/344mM/tPEtSdJpg4eXFFeSHnn7zb2WrYQ/kuRbR336wNLj5pVb8/nYu7lxnzSwvNiVqK9d8N6bHW/UjkWNb2lZ092xjlGKfKvA615Ot/XU69tHS5JufCXduPnXm3bcnLmSpBvWXJdq1KzaQebjfiuDNpTrduTOr9lrU37Nyl2jr3s5m8847d/jfNzPLSm9XV+5Dqs/R5K0W7slSX/R9ja3Xd3485bHK/ZPRYrWet/Zyv37cN/Gfy56/3l6uvzgyr3mGvVUXffe+ut+02Idqy1PtjENeXfrIUnq121IInELObFXburxQd3rJEln9J1acLu7mpYUXN8eSj4AAACAGEioAQAAgBiCLvnI11AP7DEw66EAAAAABQWdULfuQ/31IqfGznJa6thxV5cXd3GM15z3zT+VPvX4sqby450aTT1eTk1vnLhxaz7LjZ1tfe2dksp7rwGgWuTrorc1j99ruStb3fhzbWser23N0pwUpx6XpO27Pqz6mtFq2H1Qu9v9ftcjey1P6lFar4qnd81vefzznS9IksY253qM/7+mfyvpWO2h5AMAAACIIeg71LTNAwAAQOiCTqiZerzr6lszVJJ0RP0F7W63svGeNIYDdFoT6s9reVzO9PJxjO41pmJxP9hdetwvj03n9S54f23L42KvXUm5eOTMVOON6Dk2uLi/3bb/lOKn1je0PJ4yeEfJ8Ra/3avlcb7N6VUHlX5+/bJxbcn7VLPG5nVa0DS7pH1+pRdjx23+YJsk6f2t8Y+VR8kHAAAAEAMJNQAAABBD0CUf1FADAAAgdEEn1NRQd11bm/8siRppIK7nG++V9FNJ0s2vlt7+Mo5ZO2ZGcVNuNRrFveW19NtQbm3O1famf+36sSTprvUpv9c7Z3aKuCtbTeF90ysxY0dtTm9Kvc3pj1OOh0qi5AMAAACIIdGE2syGmdn9ZrbGzJab2aNmNj56boCZvWFmd7Sz/+lmNjfJMQIAAABxJFbyYWYm6UFJ89z93GjdRElDJf1J0vWSftPeMfIlH8N6jrzovOEXS5L+c9PGduOeWD+k7DFXsgVUWnGXNG7U8QPaf83PvF/4PVvadFfL45kHX9Pm/k++807B9ZMHHljECPd46r13Wx4PqBkpSTqh9gslHSOuuHFPH1baa84b2Sf3Gf/zoaV/xvPfelcfqy8vbmtXNnxTD276Y+zjFKt3TW7MB9WfllrMrhb3lcZHOt4IQKb+auBZRW/70nsPJjgSZCnJGuqpkna5+5z8CndfIUlmdoxyifVjko5NcAwAAABAopIs+Zggafm+K82sm6TZkr6SYGwAAAAgFVl8KfELkh519zfa28jMZpjZMjNbtu2DrSkNDQAAAChNkiUfqySdXWD9CZImm9kXJPWTdICZbXH3q1pv5O5zJc2VJDPzW14rrh3U0qbyB5x1C6hy48Z5zXk3rLmu5H1+t6n8eCc3z4yOcWf5B8kgbrmveda2XNxrXyzvM47zXn9Xufr42WvTbam2vfkoSenXAVdbXFSfifUXpharX82w1GPm425pfivVmOWiLhpSsneoF0rqaWYz8ivM7EhJc9x9jLs3KFf28a/7JtMAAABAZ5FYQu3uLuksSdOjtnmrJN0oqXP8LycAAABQhERnSnT3DZLOaef5nyo/xVcBTD0OAACA0DH1eBU7ov6ClseXjm6/P/Jvtqzdb93kvg1tbv/U1v23b21kz9z0vV8Y1Xbcto5x0oC243Yk3/P7y2M77ge94P3940/tX17sUVHcK8aU1+N80eb9x1KqI+ovYKp3oAtY0TgvtVhnNo9OPWbruGk7ov4C9a0Z2vK4LVxLsS+mHgcAAABiCPoONSUfAAAACF3QCXXrqccvHHnxXs+1nsa6tU8OGlR2vLG9c3+Wb28a7iTEifvkO+/o4yVMAf6frd633zXeKenHkqTvryu9pdrKxpJ3abF+Z67k4843Sm8jFyduvkXhLa+V176u3Nj5uN97Pd2WjDm5z5g/UQKoJhPqzytqu+cb7215vLLxHm1tHtvyGCgWJR8AAABADCTUAAAAQAxBl3zka6jragZmPRQAAACgoKISajMbL+kHkoa6+4RoxsMz3D3RgtDWbfO+82pxNb5xpmietT1X53rDmpSnHo8ZN85rBgCgK2pdGw0krdiSj7slXS1plyS5+3OSzk1qUAAAAEBnUWzJRx93X2pmrdc1JzCevdA2DwAAAKErNqF+x8wOluSSZGZnS3ozsVFFmCkRAIA9jqu7WFPqh6QWb0w0y+s/jitvltc04y5u3FiR2ANqRkjKvddAsYpNqC+VNFfSh8xsvaRXJRXX4BEAAADowopNqN3dp5tZX0nd3H2zmY1LcmAAAABAZ1DslxJ/IUnuvtXdN0frHkhmSHuY2elmNjfpOAAAAEC52r1DbWYfkvRhSbVm9jetnhogqVeSA5OooQYAoLWlTXdpaVN68WbtyLV1/c6rKbeTzSiuJJ3SnIu9tOmulCPfkXI8VFJHJR+HSjpNUp327raxWRJJLgAAAKpeuwm1uz8k6SEzO8Hdf5fSmAAAAIBOo9ga6nVm9qCZbYx+fmFmoxIdmaihBgAAQPiK7fLxE0n3Sfqf0fL50bqTkhhUHjXUQOWcWHtFqvHqakYRFwBQFYq9Qz3E3X/i7s3Rz08lDU5wXAAAAECnUGxC/Y6ZnW9m3aOf8yW9m+TAJEo+AAAAEL5iSz7+XtLtkm5Vbvrx30r6XFKDyqPkA6icJZu+l2q8KVHrKeKmYXYGMQEAeUUl1O7+mqQzEh4LAAAA0Ol0NLHLNe087e5+fYXHAwAAAHQqHd2h3lpgXV9Jn5d0oKREE2ozO117TygDAAAABKWjiV1aCvPMrL+kLypXO32/Uijao4YaAAAAoeuwhtrMBkr6sqTzJM2T9BF3b0x6YAAAAEBn0FEN9c2S/kbSXElHuPuWVEa1Jz4lHwAAAAhaR3eor5S0U9JMSd8ws/x6U+5LiQMSHBslHwBQgkm1l6Uar7ZmZFXFzTo2gHB1VENd7MQvAAAAQFUiYQYAAABiKHamxExQQw0AAIDQBZ1QU0MNAMV7etMdqcabHk23Xi1xs419a8rxAJSCkg8AAAAghkQTajMbZmb3m9kaM1tuZo+a2Ylm9gcze9bMVpnZJUmOAQAAAEhSYiUfluux96Ckee5+brRuoqQ6SSe4+04z6yfpeTN72N03FDgGNdQJOr7ukoKP0zCgZgRxU3Z83SV6pmlOZvEBAOiqkrxDPVXSLndv+Rfc3Ve4+xJ33xmt6tneGNx9vrvPSHCMAAAAQCxJJtQTJC0v9ISZjTaz5yStk/TtQnenAQAAgM4gky8luvs6dz9S0iGSLjSzoftuY2YzzGyZmS1Lf4QAAABAcZJsm7dK0tntbeDuG8zseUmTJT2wz3NzJc2VJDPzpAZZzXL1tLe3epyeT0Wtp4ibhmw+YwAAqkWSd6gXSuppZi010GZ2pJlNNrPe0XK9pI9LejHBcQAAAACJSewOtbu7mZ0l6TYz+5qkHZLWSvoPSd+P7jqbpO+6+8qkxgEAAAAkKdGZEqMvG55T4Km7i9mftnkAAAAIXdAzJdI2DwAAAKELOqEGAAAAQpdoyUdclHwAAAAgdEEn1O4+X9L8/jVDLzq633mJx6utGSlJmlx7eeKxQoj71KbbU40HAADQFVHyAQAAAMRAQg0AAADEEHTJR76Gule32qyHAgAAABQUdEKdr6E2s4vSqPedFk0PnXZtcVZxAQAAEB8lHwAAAEAMJNQAAABADEGXfNCHGgCAPSbWX5hqvH41w6oqbtax0XkFfYeaqccBAAAQuqATagAAACB0lHwAAAAAMQSdULdum5f1WAAAyNqKxnmpxjuzeXRVxc029g9TjodKouQDAAAAiIGEGgAAAIgh6JIPaqgBAAAQuqATamqogco5ti7dX6P+NcOJCwCoCpR8AAAAADEEfYeakg8AAACELuiEmpIPoHKWNd2darxTm2cSNzV3ZhATAJBHyQcAAAAQAwk1AAAAEEPQJR/UUAMAACB0Qd+hdvf57j4j63EAAAAAbQk6oQYAAABCR8kHAAAAEEPQCTVt8wCgeJNqL0s1Xm3NyKqKm3VsAOGi5AMAAACIgYQaAAAAiCHokg9qqAEAABC6oBNqaqgBoHhPb7oj1XjTo+nWqyVutrFvTTkegFJQ8gEAAADEQEINAAAAxJBoQm1mw8zsfjNbY2bLzexRMzvOzH5nZqvM7Dkz+9t29j/dzOYmOUYAAAAgjsRqqM3MJD0oaZ67nxutmyipTtL/dveXzGyEpOVm9mt3b9r3GNRQJ2dy7eXtLict38uVuOmZXHu5ntp0e2bxAQDoqpL8UuJUSbvcfU5+hbuvaL2Bu28ws42SBkvaL6EGAAAAQpdkQj1B0vL2NjCz4yQdIGlNgedmSJqRzNAAAACAysisbZ6ZDZd0j6QL3X33vs+7+1xJc6NtPeXhdXl7/vR/yz7L6ZgWtZ4ibhqy+YwBAKgWSX4pcZWkYwo9YWYDJP1S0jfc/ZkExwAAAAAkKsmEeqGknlHphiTJzI40sxOV+7Liv7r7AwnGBwAAABKXWMmHu7uZnSXpNjP7mqQdktZKekbSJyQdaGafjTb/rLs/u+8xmHocAAAAoUu0htrdN0g6p8BT1xe5P23zAAAAEDRmSgQAAABiyKzLRzEo+QAAAEDogk6o8yUfA2qGX3R8/wsTj1dfM1qSdFLdlYnHCiHugqbZqcYDAADoiij5AAAAAGIgoQYAAABiCLrkI19D3btbXdZDAQAAAAoKOqFu3TYvjXrfj0XTQ6ddW5xVXAAAAMRHyQcAAAAQAwk1AAAAEEPQJR/0oQYAAEDogr5D7e7z3X1G1uMAAAAA2hJ0Qg0AAACEjpIPAAAAIIag71BT8gEAAIDQBZ1QAwAAAKEjoQYAAABioIYaAAAAiCHoO9TUUAMAACB0QSfUAAAAQOgo+QAAAABiCPoONSUfAAAACF3QCTUAAAAQOhJqAAAAIAZqqAEAAIAYgr5DTQ01AAAAQhd0Qg0AAACEjoQaAAAAiIEaagAAACCGoO9QU0MNAACA0AWdUAMAAACho+QDAAAAiCHoO9SUfAAAACB0QSfUAAAAQOhIqAEAAIAYEk2ozWyYmd1vZmvMbLmZPWpm483sMTNrMrNHOtj/dDObm+QYAQAAgDgSS6jNzCQ9KGmxux/s7sdIulrSUEk3S7qgo2NQQw0AAIDQJdnlY6qkXe4+J7/C3VfkH5vZlARjAwAAAKlIMqGeIGl5uTub2QxJ3J0GAABA0Mzdkzmw2RWSxrn7/2nj+SmSvuLupxVxrM2SXqzsCIGKGSTpnawHARTAuYmQcX4iVIe6e/9SdkjyDvUqSWdX6FgvuvuxFToWUFFmtozzEyHi3ETIOD8RKjNbVuo+SXb5WCipZ1S6IUkysyPNbHKCMQEAAIBUJZZQe66W5CxJ06O2eask3SjpLTN7StK/Sfqkmb1hZp9KahwAAABAkpIs+ZC7b5B0ToGnSr1LTS9qhIzzE6Hi3ETIOD8RqpLPzcS+lAgAAABUA6YeBwAAAGIILqE2s9FmtsjMXjCzVWb2xWj9P5nZejN7Nvr5TNZjRXUxs15mttTMVkTn5rXR+nFm9nsze9nMfmZmB2Q9VlSfds7Pn5rZq62unUdlPVZUJzPrbmZ/NLNHomWunQhCgXOz5OtmcAm1pGZJV7r74ZKOl3SpmR0ePXerux8V/Tya3RBRpXZKmubuEyUdJenTZna8pG8rd24eIqlR0uczHCOqV1vnpyR9tdW189nshogq90VJq1stc+1EKPY9N6USr5vBJdTu/qa7/yF6vFm5Fzgy21EBuc417r4lWuwR/bikaZIeiNbPk3RmBsNDlWvn/AQyZ2ajJJ0q6YfRsolrJwKw77lZruAS6tbMrEHS0ZJ+H626zMyeM7Mfm1l9ZgND1Yr+LPSspI2SFkhaI6nJ3ZujTd4Q/wOIjOx7frp7/tr5rejaeauZ9cxwiKhet0n6R0m7o+UDxbUTYdj33Mwr6boZbEJtZv0k/ULSl9z9fUk/kHSwcn/KfFPS7AyHhyrl7h+4+1GSRkk6TtKHMh4S0GLf89PMJki6Wrnz9KOSBkr6WoZDRBUys9MkbXT35VmPBWitnXOz5OtmkAm1mfVQLpm+193/XZLc/c/RPxa7Jd2tXDIDZMLdmyQtknSCpDozy/d0HyVpfWYDA7TX+fnpqIzO3X2npJ+IayfSN0nSGWa2VtL9ypV6/Iu4diJ7+52bZvZ/y7luBpdQR3VVP5K02t1vabV+eKvNzpL0fNpjQ3Uzs8FmVhc97i3pJOVq/BdJOjva7EJJD2UzQlSzNs7P/85fO6Nr65ni2omUufvV7j7K3RsknStpobufJ66dyFgb5+b55Vw3E50psUyTJF0gaWVUCyhJX5f0v6K2JS5praSLsxkeqthwSfPMrLty/zP6c3d/xMxekHS/md0g6Y/K/Q8hkLa2zs+FZjZYkkl6VtIlWQ4SaOVr4tqJMN1b6nWTmRIBAACAGIIr+QAAAAA6ExJqAAAAIAYSagAAACAGEmoAAAAgBhJqAAAAIIYQ2+YBAAowswMlPRktDpP0gaS3o+Vt7v6xTAYGAFWOtnkA0AmZ2T9J2uLu3816LABQ7Sj5AIAuwMy2RP+dYmZLzOwhM3vFzG4ys/PMbKmZrTSzg6PtBpvZL8zsv6KfSdm+AgDovEioAaDrmajczF6HKTfz7Hh3P07SDyVdHm3zL5JudfePSvof0XMAgDJQQw0AXc9/ufubkmRmayS1gmqtAAAApklEQVQ9Hq1fKWlq9Hi6pMPNLL/PADPr5+5bUh0pAHQBJNQA0PXsbPV4d6vl3dpz3e8m6Xh335HmwACgK6LkAwCq0+PaU/4hMzsqw7EAQKdGQg0A1ekKScea2XNm9oJyNdcAgDLQNg8AAACIgTvUAAAAQAwk1AAAAEAMJNQAAABADCTUAAAAQAwk1AAAAEAMJNQAAABADCTUAAAAQAwk1AAAAEAM/x/Ns00pza4uPQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Get and downbeat times\n", "beats = pm.get_beats()\n", "downbeats = pm.get_downbeats()\n", "# Plot piano roll\n", "plt.figure(figsize=(12, 4))\n", "plot_piano_roll(pm, 24, 84)\n", "ymin, ymax = plt.ylim()\n", "# Plot beats as grey lines, downbeats as white lines\n", "mir_eval.display.events(beats, base=ymin, height=ymax, color='#AAAAAA')\n", "mir_eval.display.events(downbeats, base=ymin, height=ymax, color='#FFFFFF', lw=2)\n", "# Only display 20 seconds for clarity\n", "plt.xlim(25, 45);" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Harmonic information\n", "\n", "Beyond metrical information, `pretty_midi` contains a few utility functions for measuring statistics about the harmonic content of the MIDI sequence. However, it's also designed so that additional analysis is easy." ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "Text(0, 0.5, 'Proportion')" ] }, "execution_count": 26, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\n", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# Plot a pitch class distribution - sort of a proxy for key\n", "plt.bar(np.arange(12), pm.get_pitch_class_histogram());\n", "plt.xticks(np.arange(12), ['C', '', 'D', '', 'E', 'F', '', 'G', '', 'A', '', 'B'])\n", "plt.xlabel('Note')\n", "plt.ylabel('Proportion')" ] }, { "cell_type": "code", "execution_count": 28, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "60 C-to-D transitions.\n" ] } ], "source": [ "# Let's count the number of transitions from C to D in this song\n", "n_c_to_d = 0\n", "for instrument in pm.instruments:\n", " # Drum instrument notes don't have pitches!\n", " if instrument.is_drum:\n", " continue\n", " for first_note, second_note in zip(instrument.notes[:-1], instrument.notes[1:]):\n", " n_c_to_d += (first_note.pitch % 12 == 0) and (second_note.pitch % 12 == 2)\n", "print('{} C-to-D transitions.'.format(n_c_to_d))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Utility functions\n", "\n", "Since the MIDI specification is not a terribly user-friendly format (e.g. instruments are identified by integers with no discernible order), `pretty_midi` provides various functions for converting between MIDI format and human-friendly/readable format." ] }, { "cell_type": "code", "execution_count": 29, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Program number 42 is Cello\n", "... and has instrument class Strings\n", "Bassoon has program number 70\n" ] } ], "source": [ "print('Program number 42 is {}'.format(pretty_midi.program_to_instrument_name(42)))\n", "print('... and has instrument class {}'.format(pretty_midi.program_to_instrument_class(42)))\n", "print('Bassoon has program number {}'.format(pretty_midi.instrument_name_to_program('Bassoon')))" ] }, { "cell_type": "code", "execution_count": 31, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Splash Cymbal has note number 55 on drum instruments\n" ] } ], "source": [ "print('Splash Cymbal has note number {} on drum instruments'.format(\n", " pretty_midi.drum_name_to_note_number('Splash Cymbal')))" ] }, { "cell_type": "code", "execution_count": 32, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "A pitch bend value of 1000 is 0.244 semitones\n", "To pitch bend by -1.3 semitones, use the value -5324\n" ] } ], "source": [ "print('A pitch bend value of 1000 is {:.3f} semitones'.format(\n", " pretty_midi.pitch_bend_to_semitones(1000)))\n", "print('To pitch bend by -1.3 semitones, use the value {}'.format(\n", " pretty_midi.semitones_to_pitch_bend(-1.3)))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Additional resources\n", "\n", "As mentioned above, [the docs](http://craffel.github.io/pretty-midi/) cover all of the functionality in `pretty_midi`. For additional usage examples, check the [examples directory](https://github.com/craffel/pretty-midi/tree/master/examples). If you encounter an issue or have a feature request, feel free to [create an issue](https://github.com/craffel/pretty-midi/issues/new)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.6.6" } }, "nbformat": 4, "nbformat_minor": 2 }