{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Digital Musicology Tutorium Week 4: MIDI Data Explorations"
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [],
"source": [
"# import packages\n",
"using DigitalMusicology\n",
"using DataFrames\n",
"using Plots"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1) Convert Frequencies to Pitches and vice verca"
]
},
{
"cell_type": "code",
"execution_count": 24,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"pitch_to_frequency (generic function with 1 method)"
]
},
"execution_count": 24,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A4 is set to 440Hz\n",
"frequency_to_pitch(f) = 69 + 12 * log2(f / 440)\n",
"\n",
"pitch_to_frequency(p) = 2^((p - 69) / 12) * 440"
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"261.6255653005986"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# the frequency of C4\n",
"pitch_to_frequency(60)"
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"(8.175798915643707, 12543.853951415975)"
]
},
"execution_count": 26,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# the lowest midi note has a frequency of about 8Hz,\n",
"# the highest about 13kHz\n",
"# humans typically hear between 20Hz and 20kHz\n",
"pitch_to_frequency(0), pitch_to_frequency(127)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2) Example of this Weeks Tutorial: Iron Maiden *Run to the hills*\n",
"[song on youtube](https://www.youtube.com/watch?v=3ZlDZPYzfm4)\n",
"\n",
"[find midi file here](http://www.maidenmidi.com/number.html)\n",
"\n",
"The midi file can also be read by Garageband and MuseScore!"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3) Read MIDI File as a DataFrame\n",
"- A MIDI file is essentially a list of **MIDI events / MIDI commands**\n",
"- There are of are **note-on**, **note-off**, and **meta events** grouped by **channels** (repesenting voices) that are grouped by **tracks** (representing instruments)\n",
"- For note events, **pitch** and **velocity** are specified\n",
"- Meta events e.g. specify the key of a piece or indicate tempo changes\n",
"- To work with a MIDI file, we convert it into a list of notes"
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
onset_ticks offset_ticks onset_wholes offset_wholes onset_secs offset_secs pitch velocity track channel key_sharps key_major 1 0 46 0//1 23//384 0.0 0.10569841666666667 42 110 7 9 0 true 2 0 160 0//1 5//24 0.0 0.3676466666666667 36 110 7 9 0 true 3 48 94 1//16 47//384 0.110294 0.2159924166666667 42 110 7 9 0 true 4 96 142 1//8 71//384 0.220588 0.3262864166666667 42 110 7 9 0 true 5 144 190 3//16 95//384 0.330882 0.4365804166666667 42 110 7 9 0 true 6 192 238 1//4 119//384 0.441176 0.5468744166666667 42 110 7 9 0 true
"
],
"text/plain": [
"6×12 DataFrames.DataFrame\n",
"│ Row │ onset_ticks │ offset_ticks │ onset_wholes │ offset_wholes │ onset_secs │\n",
"├─────┼─────────────┼──────────────┼──────────────┼───────────────┼────────────┤\n",
"│ 1 │ 0 │ 46 │ 0//1 │ 23//384 │ 0.0 │\n",
"│ 2 │ 0 │ 160 │ 0//1 │ 5//24 │ 0.0 │\n",
"│ 3 │ 48 │ 94 │ 1//16 │ 47//384 │ 0.110294 │\n",
"│ 4 │ 96 │ 142 │ 1//8 │ 71//384 │ 0.220588 │\n",
"│ 5 │ 144 │ 190 │ 3//16 │ 95//384 │ 0.330882 │\n",
"│ 6 │ 192 │ 238 │ 1//4 │ 119//384 │ 0.441176 │\n",
"\n",
"│ Row │ offset_secs │ pitch │ velocity │ track │ channel │ key_sharps │\n",
"├─────┼─────────────┼───────┼──────────┼───────┼─────────┼────────────┤\n",
"│ 1 │ 0.105698 │ 42 │ 110 │ 7 │ 9 │ 0 │\n",
"│ 2 │ 0.367647 │ 36 │ 110 │ 7 │ 9 │ 0 │\n",
"│ 3 │ 0.215992 │ 42 │ 110 │ 7 │ 9 │ 0 │\n",
"│ 4 │ 0.326286 │ 42 │ 110 │ 7 │ 9 │ 0 │\n",
"│ 5 │ 0.43658 │ 42 │ 110 │ 7 │ 9 │ 0 │\n",
"│ 6 │ 0.546874 │ 42 │ 110 │ 7 │ 9 │ 0 │\n",
"\n",
"│ Row │ key_major │\n",
"├─────┼───────────┤\n",
"│ 1 │ true │\n",
"│ 2 │ true │\n",
"│ 3 │ true │\n",
"│ 4 │ true │\n",
"│ 5 │ true │\n",
"│ 6 │ true │"
]
},
"execution_count": 27,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"notes = midifilenotes(\"Run_To_The_Hills.mid\")\n",
"head(notes)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- `key_sharps` and `key_major` have default values\n",
"- Be careful if you see the default setting `(0,true)` like here!"
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1-element DataArrays.DataArray{Int64,1}:\n",
" 0"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"notes[:key_sharps] |> unique"
]
},
{
"cell_type": "code",
"execution_count": 29,
"metadata": {
"scrolled": false
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"search: \u001b[1mm\u001b[22m\u001b[1mi\u001b[22m\u001b[1md\u001b[22m\u001b[1mi\u001b[22m\u001b[1mf\u001b[22m\u001b[1mi\u001b[22m\u001b[1ml\u001b[22m\u001b[1me\u001b[22m\u001b[1mn\u001b[22m\u001b[1mo\u001b[22m\u001b[1mt\u001b[22m\u001b[1me\u001b[22m\u001b[1ms\u001b[22m\n",
"\n"
]
},
{
"data": {
"text/markdown": [
"```\n",
"midifilenotes(file; warnings=false, overlaps=:queue, orphans=:skip)\n",
"```\n",
"\n",
"Reads a midi file and returns a `DataFrame` with one row per note. On- and offset times are given in ticks, whole notes, and seconds. The data frame has the following columns:\n",
"\n",
" * onset_ticks (Int)\n",
" * offset_ticks (Int)\n",
" * onset_wholes (Rational{Int})\n",
" * offset_wholes (Rational{Int})\n",
" * onset_secs (Rational{Int})\n",
" * offset_secs (Rational{Int})\n",
" * pitch (MidiPitch)\n",
" * velocity (Int)\n",
" * channel (Int)\n",
" * track (Int)\n",
" * key_sharps (Int)\n",
" * key_major (Bool)\n",
"\n",
"If `warnings` is `true`, warnings about encoding errors will be displayed. If two notes overlap on the same channel and track (e.g. two ons, then two offs for the same pitch) `overlaps` provides the strategy for interpreting the sequence of on and off events:\n",
"\n",
" * `:queue` matches ons and offs in a FIFO manner (first on to first off).\n",
" * `:stack` matches ons and offs in a LIFO manner (first on to last off).\n",
"\n",
"`orphans` determines what happens to on and off events without counterpart. Currently, its value is ignored and orphan events are always skipped.\n"
],
"text/plain": [
"```\n",
"midifilenotes(file; warnings=false, overlaps=:queue, orphans=:skip)\n",
"```\n",
"\n",
"Reads a midi file and returns a `DataFrame` with one row per note. On- and offset times are given in ticks, whole notes, and seconds. The data frame has the following columns:\n",
"\n",
" * onset_ticks (Int)\n",
" * offset_ticks (Int)\n",
" * onset_wholes (Rational{Int})\n",
" * offset_wholes (Rational{Int})\n",
" * onset_secs (Rational{Int})\n",
" * offset_secs (Rational{Int})\n",
" * pitch (MidiPitch)\n",
" * velocity (Int)\n",
" * channel (Int)\n",
" * track (Int)\n",
" * key_sharps (Int)\n",
" * key_major (Bool)\n",
"\n",
"If `warnings` is `true`, warnings about encoding errors will be displayed. If two notes overlap on the same channel and track (e.g. two ons, then two offs for the same pitch) `overlaps` provides the strategy for interpreting the sequence of on and off events:\n",
"\n",
" * `:queue` matches ons and offs in a FIFO manner (first on to first off).\n",
" * `:stack` matches ons and offs in a LIFO manner (first on to last off).\n",
"\n",
"`orphans` determines what happens to on and off events without counterpart. Currently, its value is ignored and orphan events are always skipped.\n"
]
},
"execution_count": 29,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"?midifilenotes"
]
},
{
"cell_type": "code",
"execution_count": 30,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6-element DataArrays.DataArray{Int64,1}:\n",
" 2\n",
" 3\n",
" 4\n",
" 5\n",
" 6\n",
" 7"
]
},
"execution_count": 30,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# this is a small pipeline\n",
"notes[:track] |> unique |> sort"
]
},
{
"cell_type": "code",
"execution_count": 31,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"6-element DataArrays.DataArray{Int64,1}:\n",
" 2\n",
" 3\n",
" 4\n",
" 5\n",
" 6\n",
" 7"
]
},
"execution_count": 31,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# it is equivalent to\n",
"sort(unique(notes[:track]))"
]
},
{
"cell_type": "code",
"execution_count": 32,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"7-element Array{String,1}:\n",
" \"meta\" \n",
" \"vocals\" \n",
" \"vocal harmony\"\n",
" \"guitar 1\" \n",
" \"guitar 2\" \n",
" \"bass\" \n",
" \"drums\" "
]
},
"execution_count": 32,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"track_names = [\"meta\", \"vocals\", \"vocal harmony\", \"guitar 1\", \"guitar 2\", \"bass\", \"drums\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"- Track 1 is reserved for meta events!\n",
"- The other tracks are for vocals, vocal harmony, guitar 1, guitar 2, bass, drums\n",
"- one row in the data frame represents one note\n",
"- the columns are the features that we know about the notes\n",
"\n",
"## 4) A look at the first bar"
]
},
{
"cell_type": "code",
"execution_count": 33,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"onset_wholes onset_ticks 1 0//1 0 2 0//1 0 3 1//16 48 4 1//8 96 5 3//16 144 6 1//4 192 7 1//4 192 8 5//16 240 9 3//8 288 10 7//16 336 11 1//2 384 12 1//2 384 13 9//16 432 14 5//8 480 15 11//16 528 16 3//4 576 17 3//4 576 18 7//8 672 19 1//1 768 20 1//1 768
"
],
"text/plain": [
"20×2 DataFrames.DataFrame\n",
"│ Row │ onset_wholes │ onset_ticks │\n",
"├─────┼──────────────┼─────────────┤\n",
"│ 1 │ 0//1 │ 0 │\n",
"│ 2 │ 0//1 │ 0 │\n",
"│ 3 │ 1//16 │ 48 │\n",
"│ 4 │ 1//8 │ 96 │\n",
"│ 5 │ 3//16 │ 144 │\n",
"│ 6 │ 1//4 │ 192 │\n",
"│ 7 │ 1//4 │ 192 │\n",
"│ 8 │ 5//16 │ 240 │\n",
"│ 9 │ 3//8 │ 288 │\n",
"│ 10 │ 7//16 │ 336 │\n",
"│ 11 │ 1//2 │ 384 │\n",
"│ 12 │ 1//2 │ 384 │\n",
"│ 13 │ 9//16 │ 432 │\n",
"│ 14 │ 5//8 │ 480 │\n",
"│ 15 │ 11//16 │ 528 │\n",
"│ 16 │ 3//4 │ 576 │\n",
"│ 17 │ 3//4 │ 576 │\n",
"│ 18 │ 7//8 │ 672 │\n",
"│ 19 │ 1//1 │ 768 │\n",
"│ 20 │ 1//1 │ 768 │"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# drums in first bar\n",
"# there are 192 ticks per quarter note\n",
"notes[1:20, [:onset_wholes, :onset_ticks]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5) Exploratory Analysis\n",
"1. Pitch histogram\n",
"1. Pitch class histogram\n",
"1. Pitch class histogram per instrument\n",
"1. Note duration histogram per instrument\n",
"1. Beat histogram (onsets per beat) per instrument"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5.1) Plot a pitch histogram"
]
},
{
"cell_type": "code",
"execution_count": 34,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"onset_ticks offset_ticks onset_wholes offset_wholes onset_secs offset_secs pitch velocity track channel key_sharps key_major 1 2976 3214 31//8 1607//384 6.838228 7.385102416666667 86 110 4 2 0 true 2 2976 3070 31//8 1535//384 6.838228 7.054220416666666 62 110 5 3 0 true 3 2976 3070 31//8 1535//384 6.838228 7.054220416666666 69 110 5 3 0 true 4 2976 3070 31//8 1535//384 6.838228 7.054220416666666 74 110 5 3 0 true 5 2976 3070 31//8 1535//384 6.838228 7.054220416666666 38 110 6 4 0 true 6 3072 3214 4//1 1607//384 7.058816 7.385102416666667 64 110 5 3 0 true
"
],
"text/plain": [
"6×12 DataFrames.DataFrame\n",
"│ Row │ onset_ticks │ offset_ticks │ onset_wholes │ offset_wholes │ onset_secs │\n",
"├─────┼─────────────┼──────────────┼──────────────┼───────────────┼────────────┤\n",
"│ 1 │ 2976 │ 3214 │ 31//8 │ 1607//384 │ 6.83823 │\n",
"│ 2 │ 2976 │ 3070 │ 31//8 │ 1535//384 │ 6.83823 │\n",
"│ 3 │ 2976 │ 3070 │ 31//8 │ 1535//384 │ 6.83823 │\n",
"│ 4 │ 2976 │ 3070 │ 31//8 │ 1535//384 │ 6.83823 │\n",
"│ 5 │ 2976 │ 3070 │ 31//8 │ 1535//384 │ 6.83823 │\n",
"│ 6 │ 3072 │ 3214 │ 4//1 │ 1607//384 │ 7.05882 │\n",
"\n",
"│ Row │ offset_secs │ pitch │ velocity │ track │ channel │ key_sharps │\n",
"├─────┼─────────────┼───────┼──────────┼───────┼─────────┼────────────┤\n",
"│ 1 │ 7.3851 │ 86 │ 110 │ 4 │ 2 │ 0 │\n",
"│ 2 │ 7.05422 │ 62 │ 110 │ 5 │ 3 │ 0 │\n",
"│ 3 │ 7.05422 │ 69 │ 110 │ 5 │ 3 │ 0 │\n",
"│ 4 │ 7.05422 │ 74 │ 110 │ 5 │ 3 │ 0 │\n",
"│ 5 │ 7.05422 │ 38 │ 110 │ 6 │ 4 │ 0 │\n",
"│ 6 │ 7.3851 │ 64 │ 110 │ 5 │ 3 │ 0 │\n",
"\n",
"│ Row │ key_major │\n",
"├─────┼───────────┤\n",
"│ 1 │ true │\n",
"│ 2 │ true │\n",
"│ 3 │ true │\n",
"│ 4 │ true │\n",
"│ 5 │ true │\n",
"│ 6 │ true │"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# select the the instruments other than the drums\n",
"not_percussive_notes = notes[notes[:track] .!= 7, :]\n",
"head(not_percussive_notes)"
]
},
{
"cell_type": "code",
"execution_count": 35,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"10-element Array{Int64,1}:\n",
" 86\n",
" 62\n",
" 69\n",
" 74\n",
" 38\n",
" 64\n",
" 71\n",
" 76\n",
" 40\n",
" 86"
]
},
"execution_count": 35,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# convert midi notes to pitch numbers\n",
"pitches = [note.pitch for note in not_percussive_notes[:pitch]]\n",
"pitches[1:10]"
]
},
{
"cell_type": "code",
"execution_count": 36,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"40 \n",
" \n",
"\n",
"60 \n",
" \n",
"\n",
"80 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"120 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"300 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"500 \n",
" \n",
"\n",
"600 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"execution_count": 36,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# plot pitch histogram\n",
"histogram(pitches, bins=collect(0:127))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5.2) Plot a pitch class histogram"
]
},
{
"cell_type": "code",
"execution_count": 37,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"250 \n",
" \n",
"\n",
"500 \n",
" \n",
"\n",
"750 \n",
" \n",
"\n",
"1000 \n",
" \n",
"\n",
"1250 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"execution_count": 37,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# plot pitch class histogram\n",
"pitch_classes = [mod(p, 12) for p in pitches]\n",
"xticks = (collect(0:11) .+ 0.5, collect(0:11))\n",
"histogram(pitch_classes, bins=12, xticks=xticks)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Looks like a C major scale!"
]
},
{
"cell_type": "code",
"execution_count": 38,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"250 \n",
" \n",
"\n",
"500 \n",
" \n",
"\n",
"750 \n",
" \n",
"\n",
"1000 \n",
" \n",
"\n",
"1250 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"execution_count": 38,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# shift the histogram so that the most prominent note is in front\n",
"shifted_xticks = (collect(0:11) .+ 0.5, [mod(pc+7, 12) for pc in 0:11])\n",
"histogram(\n",
" [mod(pc-7, 12) for pc in pitch_classes], \n",
" bins=12, \n",
" xticks=shifted_xticks\n",
")"
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"250 \n",
" \n",
"\n",
"500 \n",
" \n",
"\n",
"750 \n",
" \n",
"\n",
"1000 \n",
" \n",
"\n",
"1250 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"transform(p) = mod((p+4)*7, 12)\n",
"histogram(\n",
" transform.(pitch_classes), \n",
" bins = 12, \n",
" xticks = (transform.(collect(0:11)) .+ 0.5, (collect(0:11))), \n",
" xlim = (0,12)\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5.3) Plot a Pitch Class Histogram per Instrument"
]
},
{
"cell_type": "code",
"execution_count": 40,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"30 \n",
" \n",
"\n",
"40 \n",
" \n",
"\n",
"50 \n",
" \n",
"\n",
"vocals \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"15 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"25 \n",
" \n",
"\n",
"30 \n",
" \n",
"\n",
"35 \n",
" \n",
"\n",
"vocal harmony \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"300 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"guitar 1 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"300 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"500 \n",
" \n",
"\n",
"guitar 2 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"4 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"6 \n",
" \n",
"\n",
"7 \n",
" \n",
"\n",
"8 \n",
" \n",
"\n",
"9 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"11 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"300 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"bass \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for track in 2:6\n",
" display(\n",
" histogram(\n",
" [mod(note.pitch, 12) for note in notes[notes[:track] .== track, :pitch]], \n",
" bins = collect(0:12),\n",
" xticks = xticks,\n",
" title = track_names[track],\n",
" xlim = (0,12)\n",
" )\n",
" )\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5.4) Plot a Note Duration Histogram per Instrument"
]
},
{
"cell_type": "code",
"execution_count": 41,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1691-element DataArrays.DataArray{Rational{Int64},1}:\n",
" 119//384\n",
" 71//384\n",
" 9//16 \n",
" 71//384\n",
" 71//384\n",
" 9//16 \n",
" 71//384\n",
" 71//384\n",
" 9//16 \n",
" 71//384\n",
" 71//384\n",
" 9//16 \n",
" 71//384\n",
" ⋮ \n",
" 5//128\n",
" 5//128\n",
" 5//128\n",
" 5//128\n",
" 5//128\n",
" 5//128\n",
" 263//384\n",
" 263//384\n",
" 263//384\n",
" 5//24 \n",
" 5//24 \n",
" 5//24 "
]
},
"execution_count": 41,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"onsets = notes[notes[:track] .== 4, :onset_wholes]\n",
"offsets = notes[notes[:track] .== 4, :offset_wholes]\n",
"durations = offsets - onsets"
]
},
{
"cell_type": "code",
"execution_count": 42,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"1691-element Array{Rational{Int64},1}:\n",
" 5//16\n",
" 3//16\n",
" 5//8 \n",
" 3//16\n",
" 3//16\n",
" 5//8 \n",
" 3//16\n",
" 3//16\n",
" 5//8 \n",
" 3//16\n",
" 3//16\n",
" 5//8 \n",
" 3//16\n",
" ⋮ \n",
" 3//64\n",
" 3//64\n",
" 3//64\n",
" 3//64\n",
" 3//64\n",
" 3//64\n",
" 11//16\n",
" 11//16\n",
" 11//16\n",
" 1//4 \n",
" 1//4 \n",
" 1//4 "
]
},
"execution_count": 42,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[(d.num + 1) // d.den for d in durations]"
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"1 \n",
" \n",
"\n",
"2 \n",
" \n",
"\n",
"3 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"40 \n",
" \n",
"\n",
"60 \n",
" \n",
"\n",
"80 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"120 \n",
" \n",
"\n",
"vocals \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.2 \n",
" \n",
"\n",
"0.4 \n",
" \n",
"\n",
"0.6 \n",
" \n",
"\n",
"0.8 \n",
" \n",
"\n",
"1.0 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"5 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"15 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"25 \n",
" \n",
"\n",
"30 \n",
" \n",
"\n",
"35 \n",
" \n",
"\n",
"vocal harmony \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.0 \n",
" \n",
"\n",
"0.5 \n",
" \n",
"\n",
"1.0 \n",
" \n",
"\n",
"1.5 \n",
" \n",
"\n",
"2.0 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"600 \n",
" \n",
"\n",
"guitar 1 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.0 \n",
" \n",
"\n",
"0.5 \n",
" \n",
"\n",
"1.0 \n",
" \n",
"\n",
"1.5 \n",
" \n",
"\n",
"2.0 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"600 \n",
" \n",
"\n",
"800 \n",
" \n",
"\n",
"guitar 2 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.0 \n",
" \n",
"\n",
"0.5 \n",
" \n",
"\n",
"1.0 \n",
" \n",
"\n",
"1.5 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"400 \n",
" \n",
"\n",
"600 \n",
" \n",
"\n",
"bass \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for track in 2:6\n",
" onsets = notes[notes[:track] .== track, :onset_wholes]\n",
" offsets = notes[notes[:track] .== track, :offset_wholes]\n",
" durations = offsets - onsets\n",
" display(histogram([(d.num + 1) // d.den for d in durations], title=track_names[track]))\n",
"end"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 5.5) Plot beat histogram (onsets per beat) per instrument"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {
"scrolled": false
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.00 \n",
" \n",
"\n",
"0.25 \n",
" \n",
"\n",
"0.50 \n",
" \n",
"\n",
"0.75 \n",
" \n",
"\n",
"1.00 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"30 \n",
" \n",
"\n",
"40 \n",
" \n",
"\n",
"50 \n",
" \n",
"\n",
"60 \n",
" \n",
"\n",
"vocals \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.00 \n",
" \n",
"\n",
"0.25 \n",
" \n",
"\n",
"0.50 \n",
" \n",
"\n",
"0.75 \n",
" \n",
"\n",
"1.00 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"10 \n",
" \n",
"\n",
"20 \n",
" \n",
"\n",
"30 \n",
" \n",
"\n",
"vocal harmony \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.00 \n",
" \n",
"\n",
"0.25 \n",
" \n",
"\n",
"0.50 \n",
" \n",
"\n",
"0.75 \n",
" \n",
"\n",
"1.00 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"50 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"150 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"guitar 1 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.00 \n",
" \n",
"\n",
"0.25 \n",
" \n",
"\n",
"0.50 \n",
" \n",
"\n",
"0.75 \n",
" \n",
"\n",
"1.00 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"50 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"150 \n",
" \n",
"\n",
"200 \n",
" \n",
"\n",
"250 \n",
" \n",
"\n",
"guitar 2 \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
"\n",
"\n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
" \n",
"\n",
"0.00 \n",
" \n",
"\n",
"0.25 \n",
" \n",
"\n",
"0.50 \n",
" \n",
"\n",
"0.75 \n",
" \n",
"\n",
"1.00 \n",
" \n",
"\n",
"0 \n",
" \n",
"\n",
"50 \n",
" \n",
"\n",
"100 \n",
" \n",
"\n",
"150 \n",
" \n",
"\n",
"bass \n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
" \n",
"\n",
"y1 \n",
" \n",
" \n"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for track in 2:6\n",
" onsets = notes[notes[:track] .== track, :onset_wholes]\n",
" display(\n",
" histogram(\n",
" [o - floor(o) for o in onsets], \n",
" bins = [x*1/16 for x in 0:16], \n",
" title = track_names[track]\n",
" )\n",
" )\n",
"end"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Julia 0.6.1",
"language": "julia",
"name": "julia-0.6"
},
"language_info": {
"file_extension": ".jl",
"mimetype": "application/julia",
"name": "julia",
"version": "0.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}