In [6]:
%pylab inline

import glob
import matplotlib.pyplot as plt
import numexpr
import os
import pandas as pd
import seaborn as sns


Populating the interactive namespace from numpy and matplotlib

Preparing the data

Data loading and putting it into a suitable format

Parsing chord labels to binary pitch class sets

  • for chord label dataset
  • [x] see tools/add_pitch_class_sets.sh

Joining DataFrames from each album and track into a common DataFrame

Loading key labels and cleaning them

  • silence/key
  • [x] just root pitch class
  • [x] convert minor keys to parallel majors
  • [x] take care of trash such as D:dorian

Data sanity checks

  • in each segment the end time is greater than the start time
  • the start time of each segment is greater or equal than the end time of previous segment
  • key segments are aligned with chord segments
  • the files for each song should match between chords and keys
    • each chord and key file should span the same time interval
      • ie. end time of last chord and key segment in a song should be equal

Features for key classification

  • for each chord segment row we need the key
  • choose the length of a chord context
    • eg. 8 chords
      • with 12 pitch classes per row it makes a block of 12*16 = 192 columns per row
  • split the dataset into blocks of adjacent chords and put each block into a wide row -> new dataframe

Missing data

  • 10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9.lab was missing in the original dataset
    • we added "silence" throughout the song instead
    • better would be to perform the actual annotation and add the right data

In [3]:
def impute_missing_key_files():
    path = 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9.lab'
    if not os.path.exists(path):
        df = pd.DataFrame.from_records(
            [("0.0", "502.204082", "Silence", None)],
            columns=['start', 'end', 'key_indicator', 'key_label'])
        df.to_csv(path, sep='\t', index=None, header=None)

impute_missing_key_files()

Keys


In [4]:
files = glob.glob('data/beatles/keylab/The_Beatles/*/*.lab')
print('key files count:', len(files))
files


key files count: 180
Out[4]:
['data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/02_-_Misery.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/03_-_Anna_(Go_To_Him).lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/04_-_Chains.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/05_-_Boys.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/06_-_Ask_Me_Why.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/07_-_Please_Please_Me.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/08_-_Love_Me_Do.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/09_-_P._S._I_Love_You.lab',
 "data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/10_-_Baby_It's_You.lab",
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/11_-_Do_You_Want_To_Know_A_Secret.lab',
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/12_-_A_Taste_Of_Honey.lab',
 "data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/13_-_There's_A_Place.lab",
 'data/beatles/keylab/The_Beatles/01_-_Please_Please_Me/14_-_Twist_And_Shout.lab',
 "data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/01_-_It_Won't_Be_Long.lab",
 "data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/02_-_All_I've_Got_To_Do.lab",
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/03_-_All_My_Loving.lab',
 "data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/04_-_Don't_Bother_Me.lab",
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/05_-_Little_Child.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/06_-_Till_There_Was_You.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/07_-_Please_Mister_Postman.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/08_-_Roll_Over_Beethoven.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/09_-_Hold_Me_Tight.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/11_-_I_Wanna_Be_Your_Man.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/12_-_Devil_In_Her_Heart.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/13_-_Not_A_Second_Time.lab',
 'data/beatles/keylab/The_Beatles/02_-_With_the_Beatles/14_-_Money.lab',
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/01_-_A_Hard_Day's_Night.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/02_-_I_Should_Have_Known_Better.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/03_-_If_I_Fell.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/04_-_I'm_Happy_Just_To_Dance_With_You.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/05_-_And_I_Love_Her.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/06_-_Tell_Me_Why.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/07_-_Can't_Buy_Me_Love.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/08_-_Any_Time_At_All.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/09_-_I'll_Cry_Instead.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/10_-_Things_We_Said_Today.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/11_-_When_I_Get_Home.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/12_-_You_Can't_Do_That.lab",
 "data/beatles/keylab/The_Beatles/03_-_A_Hard_Day's_Night/13_-_I'll_Be_Back.lab",
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/01_-_No_Reply.lab',
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/02_-_I'm_a_Loser.lab",
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/03_-_Baby's_In_Black.lab",
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/04_-_Rock_and_Roll_Music.lab',
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/05_-_I'll_Follow_the_Sun.lab",
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/06_-_Mr._Moonlight.lab',
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.lab',
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/08_-_Eight_Days_a_Week.lab',
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/09_-_Words_of_Love.lab',
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/10_-_Honey_Don't.lab",
 'data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/11_-_Every_Little_Thing.lab',
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/12_-_I_Don't_Want_to_Spoil_the_Party.lab",
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/13_-_What_You're_Doing.lab",
 "data/beatles/keylab/The_Beatles/04_-_Beatles_for_Sale/14_-_Everybody's_Trying_to_Be_My_Baby.lab",
 'data/beatles/keylab/The_Beatles/05_-_Help!/01_-_Help!.lab',
 'data/beatles/keylab/The_Beatles/05_-_Help!/02_-_The_Night_Before.lab',
 "data/beatles/keylab/The_Beatles/05_-_Help!/03_-_You've_Got_To_Hide_Your_Love_Away.lab",
 'data/beatles/keylab/The_Beatles/05_-_Help!/04_-_I_Need_You.lab',
 'data/beatles/keylab/The_Beatles/05_-_Help!/05_-_Another_Girl.lab',
 "data/beatles/keylab/The_Beatles/05_-_Help!/06_-_You're_Going_To_Lose_That_Girl.lab",
 'data/beatles/keylab/The_Beatles/05_-_Help!/07_-_Ticket_To_Ride.lab',
 'data/beatles/keylab/The_Beatles/05_-_Help!/08_-_Act_Naturally.lab',
 "data/beatles/keylab/The_Beatles/05_-_Help!/09_-_It's_Only_Love.lab",
 'data/beatles/keylab/The_Beatles/05_-_Help!/10_-_You_Like_Me_Too_Much.lab',
 'data/beatles/keylab/The_Beatles/05_-_Help!/11_-_Tell_Me_What_You_See.lab',
 "data/beatles/keylab/The_Beatles/05_-_Help!/12_-_I've_Just_Seen_a_Face.lab",
 'data/beatles/keylab/The_Beatles/05_-_Help!/13_-_Yesterday.lab',
 'data/beatles/keylab/The_Beatles/05_-_Help!/14_-_Dizzy_Miss_Lizzy.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/01_-_Drive_My_Car.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown).lab',
 "data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/03_-_You_Won't_See_Me.lab",
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/04_-_Nowhere_Man.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/05_-_Think_For_Yourself.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/06_-_The_Word.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/07_-_Michelle.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/08_-_What_Goes_On.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/09_-_Girl.lab',
 "data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/10_-_I'm_Looking_Through_You.lab",
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/11_-_In_My_Life.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/12_-_Wait.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/13_-_If_I_Needed_Someone.lab',
 'data/beatles/keylab/The_Beatles/06_-_Rubber_Soul/14_-_Run_For_Your_Life.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/01_-_Taxman.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/02_-_Eleanor_Rigby.lab',
 "data/beatles/keylab/The_Beatles/07_-_Revolver/03_-_I'm_Only_Sleeping.lab",
 'data/beatles/keylab/The_Beatles/07_-_Revolver/04_-_Love_You_To.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/05_-_Here,_There_And_Everywhere.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/06_-_Yellow_Submarine.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/07_-_She_Said_She_Said.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/08_-_Good_Day_Sunshine.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/09_-_And_Your_Bird_Can_Sing.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/10_-_For_No_One.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/11_-_Doctor_Robert.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/12_-_I_Want_To_Tell_You.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/13_-_Got_To_Get_You_Into_My_Life.lab',
 'data/beatles/keylab/The_Beatles/07_-_Revolver/14_-_Tomorrow_Never_Knows.lab',
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/02_-_With_A_Little_Help_From_My_Friends.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/04_-_Getting_Better.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/05_-_Fixing_A_Hole.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/06_-_She's_Leaving_Home.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/07_-_Being_For_The_Benefit_Of_Mr._Kite!.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/09_-_When_I'm_Sixty-Four.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/10_-_Lovely_Rita.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning.lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).lab",
 "data/beatles/keylab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/13_-_A_Day_In_The_Life.lab",
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/01_-_Magical_Mystery_Tour.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/02_-_The_Fool_On_The_Hill.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/03_-_Flying.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/05_-_Your_Mother_Should_Know.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/06_-_I_Am_The_Walrus.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/07_-_Hello_Goodbye.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/08_-_Strawberry_Fields_Forever.lab',
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/09_-_Penny_Lane.lab',
 "data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/10_-_Baby_You're_A_Rich_Man.lab",
 'data/beatles/keylab/The_Beatles/09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_01_-_Back_in_the_USSR.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_02_-_Dear_Prudence.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_03_-_Glass_Onion.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_07_-_While_My_Guitar_Gently_Weeps.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_09_-_Martha_My_Dear.lab',
 "data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_10_-_I'm_So_Tired.lab",
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_11_-_Black_Bird.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_12_-_Piggies.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_13_-_Rocky_Raccoon.lab',
 "data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_14_-_Don't_Pass_Me_By.lab",
 "data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.lab",
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_16_-_I_Will.lab',
 'data/beatles/keylab/The_Beatles/10CD1_-_The_Beatles/CD1_-_17_-_Julia.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_01_-_Birthday.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues.lab',
 "data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_03_-_Mother_Nature's_Son.lab",
 "data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_My_Monkey.lab",
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_05_-_Sexy_Sadie.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_06_-_Helter_Skelter.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_08_-_Revolution_1.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_09_-_Honey_Pie.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_10_-_Savoy_Truffle.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_11_-_Cry_Baby_Cry.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9.lab',
 'data/beatles/keylab/The_Beatles/10CD2_-_The_Beatles/CD2_-_13_-_Good_Night.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/01_-_Come_Together.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/02_-_Something.lab',
 "data/beatles/keylab/The_Beatles/11_-_Abbey_Road/03_-_Maxwell's_Silver_Hammer.lab",
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/04_-_Oh!_Darling.lab',
 "data/beatles/keylab/The_Beatles/11_-_Abbey_Road/05_-_Octopus's_Garden.lab",
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/06_-_I_Want_You.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/07_-_Here_Comes_The_Sun.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/08_-_Because.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/09_-_You_Never_Give_Me_Your_Money.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/10_-_Sun_King.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/11_-_Mean_Mr_Mustard.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/12_-_Polythene_Pam.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/13_-_She_Came_In_Through_The_Bathroom_Window.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/14_-_Golden_Slumbers.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/15_-_Carry_That_Weight.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/16_-_The_End.lab',
 'data/beatles/keylab/The_Beatles/11_-_Abbey_Road/17_-_Her_Majesty.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/01_-_Two_of_Us.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/02_-_Dig_a_Pony.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/03_-_Across_the_Universe.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/04_-_I_Me_Mine.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/05_-_Dig_It.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/06_-_Let_It_Be.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/07_-_Maggie_Mae.lab',
 "data/beatles/keylab/The_Beatles/12_-_Let_It_Be/08_-_I've_Got_A_Feeling.lab",
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/09_-_One_After_909.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/10_-_The_Long_and_Winding_Road.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/11_-_For_You_Blue.lab',
 'data/beatles/keylab/The_Beatles/12_-_Let_It_Be/12_-_Get_Back.lab']

In [5]:
def read_key_file(path):
    return pd.read_csv(path, sep='\t', header=None, names=['start','end','key_indicator','key_label'])

In [6]:
read_key_file(files[0])


Out[6]:
start end key_indicator key_label
0 0.000 1.035 Silence NaN
1 1.035 171.880 Key E
2 171.880 175.800 Silence NaN

In [7]:
def add_track_id(df, track_id):
    df['track_id'] = track_id
    return df

In [8]:
keys = pd.concat(add_track_id(read_key_file(file), track_id) for (track_id, file) in enumerate(files))

In [9]:
keys


Out[9]:
start end key_indicator key_label track_id
0 0.000 1.035 Silence NaN 0
1 1.035 171.880 Key E 0
2 171.880 175.800 Silence NaN 0
0 0.000 0.395 Silence NaN 1
1 0.395 105.685 Key C 1
2 105.685 110.160 Silence NaN 1
0 0.000 0.410 Silence NaN 2
1 0.410 174.120 Key D 2
2 174.120 177.573 Silence NaN 2
0 0.000 146.493 Key Bb 3
0 0.000 147.507 Key E 4
0 0.000 147.760 Key E 5
0 0.000 123.373 Key E 6
0 0.000 142.760 Key G 7
0 0.000 125.733 Key D:aeolian 8
0 0.000 158.067 Key G 9
0 0.000 119.333 Key E 10
0 0.000 125.133 Key F#:minor 11
0 0.000 112.867 Key E 12
0 0.000 153.267 Key D 13
0 0.000 1.030 Silence NaN 14
1 1.030 129.940 Key E 14
2 129.940 133.733 Silence NaN 14
0 0.000 0.429 Silence NaN 15
1 0.429 120.271 Key E 15
2 120.271 124.533 Silence NaN 15
0 0.000 0.383 Silence NaN 16
1 0.383 125.530 Key E 16
2 125.530 129.560 Silence NaN 16
0 0.000 0.430 Silence NaN 17
... ... ... ... ... ...
2 229.350 234.800 Silence NaN 169
0 0.000 0.355 Silence NaN 170
1 0.355 222.650 Key D 170
2 222.650 228.560 Silence NaN 170
0 0.000 0.375 Silence NaN 171
1 0.375 144.340 Key A:minor 171
2 144.340 145.733 Silence NaN 171
0 0.000 1.480 Silence NaN 172
1 1.480 50.000 Key F 172
2 50.000 50.000 Silence NaN 172
0 0.000 241.355 Key C 173
1 241.355 243.307 Silence NaN 173
0 0.000 0.345 Silence NaN 174
1 0.345 38.005 Key G 174
2 38.005 40.600 Silence NaN 174
0 0.000 0.395 Silence NaN 175
1 0.395 214.135 Key A 175
2 214.135 217.960 Silence NaN 175
0 0.000 0.350 Silence NaN 176
1 0.350 170.535 Key B 176
2 170.535 175.507 Silence NaN 176
0 0.000 0.345 Silence NaN 177
1 0.345 215.990 Key Eb 177
2 215.990 217.867 Silence NaN 177
0 0.000 0.450 Silence NaN 178
1 0.450 149.205 Key D 178
2 149.205 152.733 Silence NaN 178
0 0.000 0.365 Silence NaN 179
1 0.365 185.355 Key A:mixolydian 179
2 185.355 187.093 Silence NaN 179

408 rows × 5 columns


In [10]:
keys['duration'] = keys['end'] - keys['start']

In [11]:
keys['key_label'].value_counts()


Out[11]:
A               51
G               40
E               35
C               28
A:minor         25
D               25
F               13
E:minor         11
D:minor          9
C:minor          8
B                6
Eb               6
Bb               5
F:minor          5
C#:minor         4
F#:minor         2
G:mixolydian     2
Db               1
F:dorian         1
D:aeolian        1
A:mixolydian     1
C#:modal         1
F#               1
D:mixolydian     1
Eb:minor         1
Ab               1
dtype: int64

In [12]:
print('total number of key segments:', len(keys))


total number of key segments: 408

In [13]:
keys['duration'].describe()


Out[13]:
count    408.000000
mean      71.893412
std       81.089744
min       -0.043000
25%        3.849000
50%       27.304000
75%      143.846750
max      502.204082
Name: duration, dtype: float64

In [14]:
sns.distplot(keys['duration'], bins=50)
title('distribution of key segment duration (sec)');



In [15]:
keys['key_indicator'].value_counts()


Out[15]:
Key        284
Silence    124
dtype: int64

In [16]:
# Total duration of segments with some key and with silence:
keys.groupby('key_indicator').sum()['duration']


Out[16]:
key_indicator
Key              28589.011000
Silence            743.501082
Name: duration, dtype: float64

In [17]:
# The same in percentage:
keys.groupby('key_indicator').sum()['duration'] / keys['duration'].sum() * 100


Out[17]:
key_indicator
Key              97.465266
Silence           2.534734
Name: duration, dtype: float64

Distribution of number of key segments among songs.


In [18]:
keys.groupby('track_id').count()['start'].describe()


Out[18]:
count    180.000000
mean       2.266667
std        2.372091
min        1.000000
25%        1.000000
50%        1.000000
75%        3.000000
max       18.000000
Name: start, dtype: float64

We need to map symbolic key labels to pitch classes. Since the label are not always referring to the diatonic key but sometimes to modes, we normalize the pitch class to represent the underlying diatonic key. This would help in our further classification since it reduces the number of classes and their meaning. In order key we can limit ourselves not to discriminate between modes.


In [19]:
diatonic_pitch_classes = {'C': 0, 'D': 2, 'E': 4, 'F': 5, 'G': 7, 'A': 9, 'B': 11}
accidental_shifts = {'': 0, 'b': -1, '#': 1}
mode_shifts = {
    '': 0,
    'major': 0,
    'ionian': 0,
    'dorian': -2,
    'phrygian': -4,
    'lydian': -5,
    'mixolydian': -7,
    'aeolian': -9,
    'minor': -9,
    'locrian': -11}

def tone_label_to_pitch_class(label):
    base = label[0].upper()
    pitch_class = diatonic_pitch_classes[base]
    accidental = label[1] if len(label) > 1 else ''
    shift = accidental_shifts[accidental]
    return ((pitch_class + shift) + 12) % 12

def diatonic_root_for_key_label(key_label):
    if type(key_label) is not str:
        return
    parts = key_label.split(':')
    modal_root_label = parts[0]
    modal_root_pitch_class = tone_label_to_pitch_class(modal_root_label)
    mode_label = parts[1].lower() if len(parts) > 1 else ''
    mode_shift = mode_shifts[mode_label] if mode_label in mode_shifts else 0
    diatonic_root = modal_root_pitch_class + mode_shift
#     return (modal_root_label, mode_label, modal_root_pitch_class, mode_shift, diatonic_root)
    return (diatonic_root + 12) % 12
    
unique_key_labels = list(keys['key_label'].value_counts().index)
[(label, diatonic_root_for_key_label(label)) for label in unique_key_labels]


Out[19]:
[('A', 9),
 ('G', 7),
 ('E', 4),
 ('C', 0),
 ('A:minor', 0),
 ('D', 2),
 ('F', 5),
 ('E:minor', 7),
 ('D:minor', 5),
 ('C:minor', 3),
 ('B', 11),
 ('Eb', 3),
 ('Bb', 10),
 ('F:minor', 8),
 ('C#:minor', 4),
 ('F#:minor', 9),
 ('G:mixolydian', 0),
 ('Db', 1),
 ('F:dorian', 3),
 ('D:aeolian', 5),
 ('A:mixolydian', 2),
 ('C#:modal', 1),
 ('F#', 6),
 ('D:mixolydian', 7),
 ('Eb:minor', 6),
 ('Ab', 8)]

In [20]:
keys['key_diatonic_root'] = keys['key_label'].apply(diatonic_root_for_key_label)

In [21]:
canonic_pitch_class_labels = dict(enumerate(['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B']))
def label_for_pitch_class(pc):
    if pc in canonic_pitch_class_labels:
        return canonic_pitch_class_labels[pc]

In [22]:
keys['key_diatonic_root_label'] = keys['key_diatonic_root'].apply(label_for_pitch_class)

In [23]:
diatonic_keys_hist = keys.dropna()['key_diatonic_root_label'].value_counts()
diatonic_keys_hist


Out[23]:
C     55
A     53
G     52
E     39
D     26
F     23
Eb    15
B      6
Ab     6
Bb     5
Gb     2
Db     2
dtype: int64

In [24]:
plot(diatonic_keys_hist)
xticks(np.arange(len(diatonic_keys_hist)), diatonic_keys_hist.index)
title('diatonic key usage among all songs');



In [25]:
# all tracks start at 0.0 time
assert (keys.groupby('track_id').first()['start'] == 0).all()

# duration of each segment should be positive
# assert (keys.groupby('track_id')['duration'] < 0).all()

In [26]:
keys.groupby('track_id').last()['end']


Out[26]:
track_id
0           175.800
1           110.160
2           177.573
3           146.493
4           147.507
5           147.760
6           123.373
7           142.760
8           125.733
9           158.067
10          119.333
11          125.133
12          112.867
13          153.267
14          133.733
...
165          96.867
166         139.827
167          23.267
168         216.667
169         234.800
170         228.560
171         145.733
172          50.000
173         243.307
174          40.600
175         217.960
176         175.507
177         217.867
178         152.733
179         187.093
Name: end, Length: 180, dtype: float64

In [27]:
keys


Out[27]:
start end key_indicator key_label track_id duration key_diatonic_root key_diatonic_root_label
0 0.000 1.035 Silence NaN 0 1.035 NaN None
1 1.035 171.880 Key E 0 170.845 4 E
2 171.880 175.800 Silence NaN 0 3.920 NaN None
0 0.000 0.395 Silence NaN 1 0.395 NaN None
1 0.395 105.685 Key C 1 105.290 0 C
2 105.685 110.160 Silence NaN 1 4.475 NaN None
0 0.000 0.410 Silence NaN 2 0.410 NaN None
1 0.410 174.120 Key D 2 173.710 2 D
2 174.120 177.573 Silence NaN 2 3.453 NaN None
0 0.000 146.493 Key Bb 3 146.493 10 Bb
0 0.000 147.507 Key E 4 147.507 4 E
0 0.000 147.760 Key E 5 147.760 4 E
0 0.000 123.373 Key E 6 123.373 4 E
0 0.000 142.760 Key G 7 142.760 7 G
0 0.000 125.733 Key D:aeolian 8 125.733 5 F
0 0.000 158.067 Key G 9 158.067 7 G
0 0.000 119.333 Key E 10 119.333 4 E
0 0.000 125.133 Key F#:minor 11 125.133 9 A
0 0.000 112.867 Key E 12 112.867 4 E
0 0.000 153.267 Key D 13 153.267 2 D
0 0.000 1.030 Silence NaN 14 1.030 NaN None
1 1.030 129.940 Key E 14 128.910 4 E
2 129.940 133.733 Silence NaN 14 3.793 NaN None
0 0.000 0.429 Silence NaN 15 0.429 NaN None
1 0.429 120.271 Key E 15 119.842 4 E
2 120.271 124.533 Silence NaN 15 4.262 NaN None
0 0.000 0.383 Silence NaN 16 0.383 NaN None
1 0.383 125.530 Key E 16 125.147 4 E
2 125.530 129.560 Silence NaN 16 4.030 NaN None
0 0.000 0.430 Silence NaN 17 0.430 NaN None
... ... ... ... ... ... ... ... ...
2 229.350 234.800 Silence NaN 169 5.450 NaN None
0 0.000 0.355 Silence NaN 170 0.355 NaN None
1 0.355 222.650 Key D 170 222.295 2 D
2 222.650 228.560 Silence NaN 170 5.910 NaN None
0 0.000 0.375 Silence NaN 171 0.375 NaN None
1 0.375 144.340 Key A:minor 171 143.965 0 C
2 144.340 145.733 Silence NaN 171 1.393 NaN None
0 0.000 1.480 Silence NaN 172 1.480 NaN None
1 1.480 50.000 Key F 172 48.520 5 F
2 50.000 50.000 Silence NaN 172 0.000 NaN None
0 0.000 241.355 Key C 173 241.355 0 C
1 241.355 243.307 Silence NaN 173 1.952 NaN None
0 0.000 0.345 Silence NaN 174 0.345 NaN None
1 0.345 38.005 Key G 174 37.660 7 G
2 38.005 40.600 Silence NaN 174 2.595 NaN None
0 0.000 0.395 Silence NaN 175 0.395 NaN None
1 0.395 214.135 Key A 175 213.740 9 A
2 214.135 217.960 Silence NaN 175 3.825 NaN None
0 0.000 0.350 Silence NaN 176 0.350 NaN None
1 0.350 170.535 Key B 176 170.185 11 B
2 170.535 175.507 Silence NaN 176 4.972 NaN None
0 0.000 0.345 Silence NaN 177 0.345 NaN None
1 0.345 215.990 Key Eb 177 215.645 3 Eb
2 215.990 217.867 Silence NaN 177 1.877 NaN None
0 0.000 0.450 Silence NaN 178 0.450 NaN None
1 0.450 149.205 Key D 178 148.755 2 D
2 149.205 152.733 Silence NaN 178 3.528 NaN None
0 0.000 0.365 Silence NaN 179 0.365 NaN None
1 0.365 185.355 Key A:mixolydian 179 184.990 2 D
2 185.355 187.093 Silence NaN 179 1.738 NaN None

408 rows × 8 columns

Export the prepared DataFrame to TSV file.


In [28]:
keys = keys[[
        'track_id', 'start', 'end', 'duration', 'key_indicator',
        'key_label', 'key_diatonic_root_label', 'key_diatonic_root']]

In [29]:
keys.to_csv('data/beatles/derived/all_keys.tsv', sep='\t', index=False, float_format='%.3f')

Chords


In [30]:
files = glob.glob('data/beatles/chordlab/The_Beatles/*/*.lab.pcs.tsv')
print('chord files count:', len(files))
files


chord files count: 180
Out[30]:
['data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/01_-_I_Saw_Her_Standing_There.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/02_-_Misery.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/03_-_Anna_(Go_To_Him).lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/04_-_Chains.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/05_-_Boys.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/06_-_Ask_Me_Why.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/07_-_Please_Please_Me.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/08_-_Love_Me_Do.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/09_-_P._S._I_Love_You.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/10_-_Baby_It's_You.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/11_-_Do_You_Want_To_Know_A_Secret.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/12_-_A_Taste_Of_Honey.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/13_-_There's_A_Place.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/01_-_Please_Please_Me/14_-_Twist_And_Shout.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/01_-_It_Won't_Be_Long.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/02_-_All_I've_Got_To_Do.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/03_-_All_My_Loving.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/04_-_Don't_Bother_Me.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/05_-_Little_Child.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/06_-_Till_There_Was_You.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/07_-_Please_Mister_Postman.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/08_-_Roll_Over_Beethoven.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/09_-_Hold_Me_Tight.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/10_-_You_Really_Got_A_Hold_On_Me.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/11_-_I_Wanna_Be_Your_Man.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/12_-_Devil_In_Her_Heart.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/13_-_Not_A_Second_Time.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/02_-_With_the_Beatles/14_-_Money.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/01_-_A_Hard_Day's_Night.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/02_-_I_Should_Have_Known_Better.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/03_-_If_I_Fell.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/04_-_I'm_Happy_Just_To_Dance_With_You.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/05_-_And_I_Love_Her.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/06_-_Tell_Me_Why.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/07_-_Can't_Buy_Me_Love.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/08_-_Any_Time_At_All.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/09_-_I'll_Cry_Instead.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/10_-_Things_We_Said_Today.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/11_-_When_I_Get_Home.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/12_-_You_Can't_Do_That.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/03_-_A_Hard_Day's_Night/13_-_I'll_Be_Back.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/01_-_No_Reply.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/02_-_I'm_a_Loser.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/03_-_Baby's_In_Black.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/04_-_Rock_and_Roll_Music.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/05_-_I'll_Follow_the_Sun.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/06_-_Mr._Moonlight.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/07_-_Kansas_City-_Hey,_Hey,_Hey,_Hey.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/08_-_Eight_Days_a_Week.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/09_-_Words_of_Love.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/10_-_Honey_Don't.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/11_-_Every_Little_Thing.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/12_-_I_Don't_Want_to_Spoil_the_Party.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/13_-_What_You're_Doing.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/04_-_Beatles_for_Sale/14_-_Everybody's_Trying_to_Be_My_Baby.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/05_-_Help!/01_-_Help!.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/05_-_Help!/02_-_The_Night_Before.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/05_-_Help!/03_-_You've_Got_To_Hide_Your_Love_Away.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/05_-_Help!/04_-_I_Need_You.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/05_-_Help!/05_-_Another_Girl.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/05_-_Help!/06_-_You're_Going_To_Lose_That_Girl.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/05_-_Help!/07_-_Ticket_To_Ride.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/05_-_Help!/08_-_Act_Naturally.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/05_-_Help!/09_-_It's_Only_Love.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/05_-_Help!/10_-_You_Like_Me_Too_Much.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/05_-_Help!/11_-_Tell_Me_What_You_See.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/05_-_Help!/12_-_I've_Just_Seen_a_Face.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/05_-_Help!/13_-_Yesterday.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/05_-_Help!/14_-_Dizzy_Miss_Lizzy.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/01_-_Drive_My_Car.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/02_-_Norwegian_Wood_(This_Bird_Has_Flown).lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/03_-_You_Won't_See_Me.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/04_-_Nowhere_Man.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/05_-_Think_For_Yourself.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/06_-_The_Word.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/07_-_Michelle.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/08_-_What_Goes_On.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/09_-_Girl.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/10_-_I'm_Looking_Through_You.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/11_-_In_My_Life.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/12_-_Wait.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/13_-_If_I_Needed_Someone.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/06_-_Rubber_Soul/14_-_Run_For_Your_Life.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/01_-_Taxman.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/02_-_Eleanor_Rigby.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/07_-_Revolver/03_-_I'm_Only_Sleeping.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/04_-_Love_You_To.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/05_-_Here,_There_And_Everywhere.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/06_-_Yellow_Submarine.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/07_-_She_Said_She_Said.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/08_-_Good_Day_Sunshine.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/09_-_And_Your_Bird_Can_Sing.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/10_-_For_No_One.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/11_-_Doctor_Robert.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/12_-_I_Want_To_Tell_You.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/13_-_Got_To_Get_You_Into_My_Life.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/07_-_Revolver/14_-_Tomorrow_Never_Knows.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/01_-_Sgt._Pepper's_Lonely_Hearts_Club_Band.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/02_-_With_A_Little_Help_From_My_Friends.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/03_-_Lucy_In_The_Sky_With_Diamonds.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/04_-_Getting_Better.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/05_-_Fixing_A_Hole.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/06_-_She's_Leaving_Home.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/07_-_Being_For_The_Benefit_Of_Mr._Kite!.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/08_-_Within_You_Without_You.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/09_-_When_I'm_Sixty-Four.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/10_-_Lovely_Rita.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/11_-_Good_Morning_Good_Morning.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/12_-_Sgt._Pepper's_Lonely_Hearts_Club_Band_(Reprise).lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/08_-_Sgt._Pepper's_Lonely_Hearts_Club_Band/13_-_A_Day_In_The_Life.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/01_-_Magical_Mystery_Tour.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/02_-_The_Fool_On_The_Hill.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/03_-_Flying.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/04_-_Blue_Jay_Way.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/05_-_Your_Mother_Should_Know.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/06_-_I_Am_The_Walrus.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/07_-_Hello_Goodbye.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/08_-_Strawberry_Fields_Forever.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/09_-_Penny_Lane.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/10_-_Baby_You're_A_Rich_Man.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/09_-_Magical_Mystery_Tour/11_-_All_You_Need_Is_Love.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_01_-_Back_in_the_USSR.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_02_-_Dear_Prudence.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_03_-_Glass_Onion.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_04_-_Ob-La-Di,_Ob-La-Da.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_05_-_Wild_Honey_Pie.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_06_-_The_Continuing_Story_of_Bungalow_Bill.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_07_-_While_My_Guitar_Gently_Weeps.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_08_-_Happiness_is_a_Warm_Gun.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_09_-_Martha_My_Dear.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_10_-_I'm_So_Tired.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_11_-_Black_Bird.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_12_-_Piggies.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_13_-_Rocky_Raccoon.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_14_-_Don't_Pass_Me_By.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_15_-_Why_Don't_We_Do_It_In_The_Road.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_16_-_I_Will.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD1_-_The_Beatles/CD1_-_17_-_Julia.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_01_-_Birthday.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_02_-_Yer_Blues.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_03_-_Mother_Nature's_Son.lab.pcs.tsv",
 "data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_04_-_Everybody's_Got_Something_To_Hide_Except_Me_and_My_Monkey.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_05_-_Sexy_Sadie.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_06_-_Helter_Skelter.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_07_-_Long_Long_Long.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_08_-_Revolution_1.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_09_-_Honey_Pie.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_10_-_Savoy_Truffle.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_11_-_Cry_Baby_Cry.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_12_-_Revolution_9.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/10CD2_-_The_Beatles/CD2_-_13_-_Good_Night.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/01_-_Come_Together.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/02_-_Something.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/03_-_Maxwell's_Silver_Hammer.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/04_-_Oh!_Darling.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/05_-_Octopus's_Garden.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/06_-_I_Want_You.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/07_-_Here_Comes_The_Sun.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/08_-_Because.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/09_-_You_Never_Give_Me_Your_Money.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/10_-_Sun_King.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/11_-_Mean_Mr_Mustard.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/12_-_Polythene_Pam.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/13_-_She_Came_In_Through_The_Bathroom_Window.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/14_-_Golden_Slumbers.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/15_-_Carry_That_Weight.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/16_-_The_End.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/11_-_Abbey_Road/17_-_Her_Majesty.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/01_-_Two_of_Us.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/02_-_Dig_a_Pony.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/03_-_Across_the_Universe.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/04_-_I_Me_Mine.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/05_-_Dig_It.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/06_-_Let_It_Be.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/07_-_Maggie_Mae.lab.pcs.tsv',
 "data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/08_-_I've_Got_A_Feeling.lab.pcs.tsv",
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/09_-_One_After_909.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/10_-_The_Long_and_Winding_Road.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/11_-_For_You_Blue.lab.pcs.tsv',
 'data/beatles/chordlab/The_Beatles/12_-_Let_It_Be/12_-_Get_Back.lab.pcs.tsv']

In [31]:
def read_chord_file(path):
    return pd.read_csv(path, sep=' ', header=None, names=['start','end','chord_label'])

def read_chord_file_with_pitch_classes(path):
    return pd.read_csv(path, sep='\t')

In [32]:
read_chord_file_with_pitch_classes(files[0])


Out[32]:
start end label root bass C Db D Eb E F Gb G Ab A Bb B
0 0.000000 2.612267 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2.612267 11.459070 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
2 11.459070 12.921927 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
3 12.921927 17.443474 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
4 17.443474 20.410362 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
5 20.410362 21.908049 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
6 21.908049 23.370907 E:7/3 4 8 0 0 1 0 1 0 0 0 1 0 0 1
7 23.370907 24.856984 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
8 24.856984 26.343061 A:min/b3 9 0 1 0 0 0 1 0 0 0 0 1 0 0
9 26.343061 27.840748 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
10 27.840748 29.350045 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
11 29.350045 35.305963 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
12 35.305963 36.803650 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
13 36.803650 41.263102 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
14 41.263102 44.245646 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
15 44.245646 45.720113 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
16 45.720113 47.206190 E:7/3 4 8 0 0 1 0 1 0 0 0 1 0 0 1
17 47.206190 48.692267 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
18 48.692267 50.155124 A:min/b3 9 0 1 0 0 0 1 0 0 0 0 1 0 0
19 50.155124 51.652811 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
20 51.652811 53.138888 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
21 53.138888 56.111043 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
22 56.111043 65.131995 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
23 65.131995 68.150589 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
24 68.150589 71.192403 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
25 71.192403 74.199387 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
26 74.199387 75.697074 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
27 75.697074 80.236575 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
28 80.236575 83.208730 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
29 83.208730 86.221693 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
32 89.257528 90.720385 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
33 90.720385 92.157453 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
34 92.157453 104.106689 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
35 104.106689 107.125283 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
36 107.125283 110.178707 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
37 110.178707 113.124087 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
38 113.124087 114.613718 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
39 114.613718 116.099795 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
40 116.099795 118.944961 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
41 118.944961 128.046462 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
42 128.046462 131.053446 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
43 131.053446 134.037210 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
44 134.037210 137.044195 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
45 137.044195 138.475524 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
46 138.475524 143.058163 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
47 143.058163 146.041927 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
48 146.041927 147.551224 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
49 147.551224 149.060521 E:7/3 4 8 0 0 1 0 1 0 0 0 1 0 0 1
50 149.060521 150.511768 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
51 150.511768 152.021065 A:min/b3 9 0 1 0 0 0 1 0 0 0 0 1 0 0
52 152.021065 153.530362 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
53 153.530362 155.062879 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
54 155.062879 159.532721 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
55 159.532721 161.065238 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
56 161.065238 165.581519 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
57 165.581519 167.114036 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
58 167.114036 168.646553 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
59 168.646553 169.737409 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
60 169.737409 171.687173 E:9 4 4 0 0 1 0 1 0 1 0 1 0 0 1
61 171.687173 175.804082 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0

62 rows × 17 columns


In [33]:
chords = pd.concat(add_track_id(read_chord_file_with_pitch_classes(file), track_id) for (track_id, file) in enumerate(files))

In [34]:
chords['duration'] = chords['end'] - chords['start']

In [35]:
chords = chords.reindex_axis(['track_id', 'start', 'end', 'duration', 'label', 'root', 'bass', 'C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B'], axis=1)
chords


Out[35]:
track_id start end duration label root bass C Db D Eb E F Gb G Ab A Bb B
0 0 0.000000 2.612267 2.612267 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
5 0 20.410362 21.908049 1.497687 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
6 0 21.908049 23.370907 1.462858 E:7/3 4 8 0 0 1 0 1 0 0 0 1 0 0 1
7 0 23.370907 24.856984 1.486077 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
8 0 24.856984 26.343061 1.486077 A:min/b3 9 0 1 0 0 0 1 0 0 0 0 1 0 0
9 0 26.343061 27.840748 1.497687 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
10 0 27.840748 29.350045 1.509297 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
11 0 29.350045 35.305963 5.955918 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
12 0 35.305963 36.803650 1.497687 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
13 0 36.803650 41.263102 4.459452 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
14 0 41.263102 44.245646 2.982544 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
15 0 44.245646 45.720113 1.474467 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
16 0 45.720113 47.206190 1.486077 E:7/3 4 8 0 0 1 0 1 0 0 0 1 0 0 1
17 0 47.206190 48.692267 1.486077 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
18 0 48.692267 50.155124 1.462857 A:min/b3 9 0 1 0 0 0 1 0 0 0 0 1 0 0
19 0 50.155124 51.652811 1.497687 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
20 0 51.652811 53.138888 1.486077 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
21 0 53.138888 56.111043 2.972155 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
22 0 56.111043 65.131995 9.020952 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
23 0 65.131995 68.150589 3.018594 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
24 0 68.150589 71.192403 3.041814 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
25 0 71.192403 74.199387 3.006984 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
26 0 74.199387 75.697074 1.497687 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
27 0 75.697074 80.236575 4.539501 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
28 0 80.236575 83.208730 2.972155 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1
29 0 83.208730 86.221693 3.012963 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
54 179 120.053537 122.004013 1.950476 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
55 179 122.004013 122.967641 0.963628 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
56 179 122.967641 123.942879 0.975238 G/2 7 9 0 0 1 0 0 0 0 1 0 1 0 1
57 179 123.942879 127.843832 3.900953 A:7 9 9 0 1 0 0 1 0 0 1 0 1 0 0
58 179 127.843832 129.805918 1.962086 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
59 179 129.805918 130.792766 0.986848 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
60 179 130.792766 131.245555 0.452789 G/2 7 9 0 0 1 0 0 0 0 1 0 1 0 1
61 179 131.245555 131.756394 0.510839 D/5 2 9 0 0 1 0 0 0 1 0 0 1 0 0
62 179 131.756394 135.622517 3.866123 A:7 9 9 0 1 0 0 1 0 0 1 0 1 0 0
63 179 135.622517 137.549773 1.927256 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
64 179 137.549773 139.477029 1.927256 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
65 179 139.477029 143.308321 3.831292 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
66 179 143.308321 145.258798 1.950477 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
67 179 145.258798 146.245646 0.986848 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
68 179 146.245646 146.733265 0.487619 G/2 7 9 0 0 1 0 0 0 0 1 0 1 0 1
69 179 146.733265 147.244104 0.510839 D/5 2 9 0 0 1 0 0 0 1 0 0 1 0 0
70 179 147.244104 151.110226 3.866122 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
71 179 151.110226 153.060702 1.950476 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
72 179 153.060702 154.024331 0.963629 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
73 179 154.024331 154.523560 0.499229 G/2 7 9 0 0 1 0 0 0 0 1 0 1 0 1
74 179 154.523560 155.022789 0.499229 D/5 2 9 0 0 1 0 0 0 1 0 0 1 0 0
75 179 155.022789 158.854081 3.831292 A:7 9 9 0 1 0 0 1 0 0 1 0 1 0 0
76 179 158.854081 160.781337 1.927256 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
77 179 160.781337 161.489546 0.708209 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
78 179 161.489546 162.174535 0.684989 G/2 7 9 0 0 1 0 0 0 0 1 0 1 0 1
79 179 162.174535 162.696984 0.522449 D/5 2 9 0 0 1 0 0 0 1 0 0 1 0 0
80 179 162.696984 166.423786 3.726802 A:7 9 9 0 1 0 0 1 0 0 1 0 1 0 0
81 179 166.423786 168.192617 1.768831 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
82 179 168.192617 174.281557 6.088940 D:7 2 2 1 0 1 0 0 0 1 0 0 1 0 0
83 179 174.281557 186.984490 12.702933 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0

14621 rows × 19 columns


In [36]:
# all tracks start at 0.0 time
assert (chords.groupby('track_id').first()['start'] == 0).all()

Chords vs. keys - alignment


In [37]:
chords_keys_end_diff = chords.groupby('track_id').last()[['end']].rename(columns={'end': 'chords_end'}).join(keys.groupby('track_id').last()[['end']].rename(columns={'end': 'keys_end'}))
chords_keys_end_diff['diff'] = chords_keys_end_diff['chords_end'] - chords_keys_end_diff['keys_end']

In [38]:
chords_keys_end_diff['diff'].describe()


Out[38]:
count    180.000000
mean       0.005191
std        0.035198
min       -0.133061
25%        0.005714
50%        0.014663
75%        0.020469
max        0.039245
Name: diff, dtype: float64

Track lengths are not precisely aligned between chords and keys dataset. Roughly they're are alrigth, however.


In [39]:
chords_keys_end_diff


Out[39]:
chords_end keys_end diff
track_id
0 175.804082 175.800 0.004082
1 110.184490 110.160 0.024490
2 177.580408 177.573 0.007408
3 146.494694 146.493 0.001694
4 147.513469 147.507 0.006469
5 147.774694 147.760 0.014694
6 123.376327 123.373 0.003327
7 142.759184 142.760 -0.000816
8 125.753469 125.733 0.020469
9 158.066939 158.067 -0.000061
10 119.353469 119.333 0.020469
11 125.152653 125.133 0.019653
12 112.875102 112.867 0.008102
13 153.155918 153.267 -0.111082
14 133.746939 133.733 0.013939
15 124.551837 124.533 0.018837
16 129.567347 129.560 0.007347
17 149.394286 149.373 0.021286
18 108.016327 108.000 0.016327
19 136.751020 136.733 0.018020
20 156.734694 156.733 0.001694
21 167.627755 167.627 0.000755
22 152.581224 152.573 0.008224
23 182.909388 182.893 0.016388
24 118.987755 118.973 0.014755
25 147.670204 147.667 0.003204
26 128.339592 128.333 0.006592
27 167.444898 167.560 -0.115102
28 152.555102 152.520 0.035102
29 164.101224 164.080 0.021224
... ... ... ...
150 191.686531 191.800 -0.113469
151 260.649796 260.627 0.022796
152 183.013878 183.000 0.013878
153 207.281633 207.267 0.014633
154 206.706939 206.707 -0.000061
155 171.180408 171.160 0.020408
156 467.173878 467.173 0.000878
157 185.573878 185.560 0.013878
158 165.537959 165.533 0.004959
159 242.416327 242.400 0.016327
160 146.311837 146.307 0.004837
161 66.298776 66.293 0.005776
162 72.751020 72.733 0.018020
163 117.733878 117.733 0.000878
164 91.585306 91.573 0.012306
165 96.888163 96.867 0.021163
166 139.833469 139.827 0.006469
167 23.144490 23.267 -0.122510
168 216.685714 216.667 0.018714
169 234.814694 234.800 0.014694
170 228.571429 228.560 0.011429
171 145.737143 145.733 0.004143
172 50.024490 50.000 0.024490
173 243.330612 243.307 0.023612
174 40.620408 40.600 0.020408
175 217.965714 217.960 0.005714
176 175.516735 175.507 0.009735
177 217.887347 217.867 0.020347
178 152.737959 152.733 0.004959
179 186.984490 187.093 -0.108510

180 rows × 3 columns


In [40]:
chords_keys_end_diff['diff'].hist(bins=50);


Merge chords and keys


In [41]:
chords.head()


Out[41]:
track_id start end duration label root bass C Db D Eb E F Gb G Ab A Bb B
0 0 0.000000 2.612267 2.612267 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 0 1 0 0 0 0 1 0 0
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 1 0 0 1 0 0 0 0 1

In [42]:
keys.head()


Out[42]:
track_id start end duration key_indicator key_label key_diatonic_root_label key_diatonic_root
0 0 0.000 1.035 1.035 Silence NaN None NaN
1 0 1.035 171.880 170.845 Key E E 4
2 0 171.880 175.800 3.920 Silence NaN None NaN
0 1 0.000 0.395 0.395 Silence NaN None NaN
1 1 0.395 105.685 105.290 Key C C 0

Let's try to merge keys to chords from a single example track.


In [43]:
track_keys = keys[keys['track_id'] == 109]
track_keys


Out[43]:
track_id start end duration key_indicator key_label key_diatonic_root_label key_diatonic_root
0 109 0.000 135.830 135.830 Key G G 7
1 109 135.830 198.310 62.480 Key E E 4
2 109 198.310 259.226 60.916 Key G G 7
3 109 259.226 333.907 74.681 Key E E 4
4 109 333.907 333.907 0.000 Silence NaN None NaN

In [44]:
track_chords = chords[chords['track_id'] == 109]
track_chords


Out[44]:
track_id start end duration label root bass C Db D Eb E F Gb G Ab A Bb B
0 109 0.000000 1.914761 1.914761 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
1 109 1.914761 3.369980 1.455219 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
2 109 3.369980 6.519569 3.149589 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
3 109 6.519569 12.848047 6.328478 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
4 109 12.848047 14.425963 1.577916 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
5 109 14.425963 15.923650 1.497687 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
6 109 15.923650 17.490997 1.567347 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
7 109 17.490997 18.988684 1.497687 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
8 109 18.988684 20.556031 1.567347 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
9 109 20.556031 22.123378 1.567347 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
10 109 22.123378 25.223242 3.099864 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
11 109 25.223242 26.744149 1.520907 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
12 109 26.744149 28.369546 1.625397 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
13 109 28.369546 29.925283 1.555737 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
14 109 29.925283 31.446190 1.520907 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
15 109 31.446190 33.059977 1.613787 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
16 109 33.059977 34.592494 1.532517 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
17 109 34.592494 36.148231 1.555737 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
18 109 36.148231 37.680748 1.532517 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
19 109 37.680748 39.294535 1.613787 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
20 109 39.294535 40.815442 1.520907 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
21 109 40.815442 42.382789 1.567347 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
22 109 42.382789 43.543786 1.160997 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
23 109 43.543786 43.950136 0.406350 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
24 109 43.950136 45.517482 1.567346 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
25 109 45.517482 47.003560 1.486078 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
26 109 47.003560 50.033764 3.030204 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
27 109 50.033764 51.659160 1.625396 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
28 109 51.659160 53.145238 1.486078 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
29 109 53.145238 56.349591 3.204353 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
90 109 198.339614 199.872131 1.532517 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
91 109 199.872131 201.323378 1.451247 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
92 109 201.323378 202.855895 1.532517 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
93 109 202.855895 204.318752 1.462857 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
94 109 204.318752 205.781609 1.462857 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
95 109 205.781609 207.209637 1.428028 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
96 109 207.209637 209.136893 1.927256 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
97 109 209.136893 210.216621 1.079728 F#:hdim7 6 6 1 0 0 0 1 0 1 0 0 1 0 0
98 109 210.216621 211.656258 1.439637 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
99 109 211.656258 213.107505 1.451247 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
100 109 213.107505 214.616802 1.509297 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
101 109 214.616802 216.068049 1.451247 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
102 109 216.068049 217.554126 1.486077 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
103 109 217.554126 218.993764 1.439638 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
104 109 218.993764 220.491451 1.497687 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
105 109 220.491451 221.942698 1.451247 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
106 109 221.942698 224.856802 2.914104 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
107 109 224.856802 226.354489 1.497687 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
108 109 226.354489 227.782517 1.428028 F#:(1,4,b5) 6 6 1 0 0 0 0 0 1 0 0 0 0 1
109 109 227.782517 229.245374 1.462857 E:min/b3 4 7 0 0 0 0 1 0 0 1 0 0 0 1
110 109 229.245374 230.719841 1.474467 A:min(2) 9 9 1 0 0 0 1 0 0 0 0 1 0 1
111 109 230.719841 232.136258 1.416417 E:min(*b3)/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
112 109 232.136258 233.564285 1.428027 C:maj7(*5) 0 0 1 0 0 0 1 0 0 0 0 0 0 1
113 109 233.564285 234.992312 1.428027 E:min7(*5)/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 0
114 109 234.992312 241.336491 6.344179 E:(1,2,5,b6) 4 4 1 0 0 0 1 0 1 0 0 0 0 1
115 109 241.336491 259.316098 17.979607 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
116 109 259.316098 261.154269 1.838171 E:(1) 4 4 0 0 0 0 1 0 0 0 0 0 0 0
117 109 261.154269 303.623671 42.469402 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
118 109 303.623671 306.859617 3.235946 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119 109 306.859617 333.792653 26.933036 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0

120 rows × 19 columns


In [27]:
def plot_time_intervals(starts, ends, **kwargs):
    x_lines = [el for (s, e) in zip(starts, ends) for el in (s, e, None)]
    y_lines = [el for i in range(len(starts)) for el in (i, i, None)]
    plot(x_lines, y_lines, **kwargs)

def plot_chords_and_keys(track_chords, track_keys):
    plot_time_intervals(track_chords['start'], track_chords['end'], label='chord segments')
    plot_time_intervals(track_keys['start'], track_keys['end'], label='key segments')
    title('chord and key segments in time')
    legend(loc='center right')
    xlabel('time (sec)')
    ylabel('segment index')

In [ ]:
plot_chords_and_keys(track_chords, track_keys);

In [46]:
def time_range(df, start, end):
    return df[(df['start'] >= start) & (df['end'] <= end)]

plot_chords_and_keys(time_range(track_chords, 120, 220), time_range(track_keys, 120, 220))



In [47]:
def find_key(keys, track_id, start):
    "Finds the first key segment within a track that the chord segment spans."
    possible_keys = keys.query('(start <= '+str(start)+') & (track_id == '+str(track_id)+')')
    if len(possible_keys) > 0:
        row = possible_keys.iloc[-1]
#         return pd.Series([start, ['start']])
        return row

find_key(keys, 109, 198.0)


Out[47]:
track_id                      109
start                      135.83
end                        198.31
duration                    62.48
key_indicator                 Key
key_label                       E
key_diatonic_root_label         E
key_diatonic_root               4
Name: 1, dtype: object

In [48]:
track_chords['start'].apply(lambda start: find_key(track_keys, 109, start)[['key_diatonic_root_label', 'key_diatonic_root']])


Out[48]:
key_diatonic_root_label key_diatonic_root
0 G 7
1 G 7
2 G 7
3 G 7
4 G 7
5 G 7
6 G 7
7 G 7
8 G 7
9 G 7
10 G 7
11 G 7
12 G 7
13 G 7
14 G 7
15 G 7
16 G 7
17 G 7
18 G 7
19 G 7
20 G 7
21 G 7
22 G 7
23 G 7
24 G 7
25 G 7
26 G 7
27 G 7
28 G 7
29 G 7
... ... ...
90 G 7
91 G 7
92 G 7
93 G 7
94 G 7
95 G 7
96 G 7
97 G 7
98 G 7
99 G 7
100 G 7
101 G 7
102 G 7
103 G 7
104 G 7
105 G 7
106 G 7
107 G 7
108 G 7
109 G 7
110 G 7
111 G 7
112 G 7
113 G 7
114 G 7
115 G 7
116 E 4
117 E 4
118 E 4
119 E 4

120 rows × 2 columns


In [49]:
track_keys


Out[49]:
track_id start end duration key_indicator key_label key_diatonic_root_label key_diatonic_root
0 109 0.000 135.830 135.830 Key G G 7
1 109 135.830 198.310 62.480 Key E E 4
2 109 198.310 259.226 60.916 Key G G 7
3 109 259.226 333.907 74.681 Key E E 4
4 109 333.907 333.907 0.000 Silence NaN None NaN

In [50]:
track_chords


Out[50]:
track_id start end duration label root bass C Db D Eb E F Gb G Ab A Bb B
0 109 0.000000 1.914761 1.914761 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
1 109 1.914761 3.369980 1.455219 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
2 109 3.369980 6.519569 3.149589 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
3 109 6.519569 12.848047 6.328478 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
4 109 12.848047 14.425963 1.577916 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
5 109 14.425963 15.923650 1.497687 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
6 109 15.923650 17.490997 1.567347 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
7 109 17.490997 18.988684 1.497687 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
8 109 18.988684 20.556031 1.567347 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
9 109 20.556031 22.123378 1.567347 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
10 109 22.123378 25.223242 3.099864 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
11 109 25.223242 26.744149 1.520907 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
12 109 26.744149 28.369546 1.625397 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
13 109 28.369546 29.925283 1.555737 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
14 109 29.925283 31.446190 1.520907 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
15 109 31.446190 33.059977 1.613787 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
16 109 33.059977 34.592494 1.532517 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
17 109 34.592494 36.148231 1.555737 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
18 109 36.148231 37.680748 1.532517 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
19 109 37.680748 39.294535 1.613787 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
20 109 39.294535 40.815442 1.520907 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
21 109 40.815442 42.382789 1.567347 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
22 109 42.382789 43.543786 1.160997 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
23 109 43.543786 43.950136 0.406350 D 2 2 0 0 1 0 0 0 1 0 0 1 0 0
24 109 43.950136 45.517482 1.567346 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
25 109 45.517482 47.003560 1.486078 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
26 109 47.003560 50.033764 3.030204 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
27 109 50.033764 51.659160 1.625396 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
28 109 51.659160 53.145238 1.486078 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
29 109 53.145238 56.349591 3.204353 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
90 109 198.339614 199.872131 1.532517 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
91 109 199.872131 201.323378 1.451247 B:min/5 11 6 0 0 1 0 0 0 1 0 0 0 0 1
92 109 201.323378 202.855895 1.532517 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
93 109 202.855895 204.318752 1.462857 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
94 109 204.318752 205.781609 1.462857 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
95 109 205.781609 207.209637 1.428028 E:min/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
96 109 207.209637 209.136893 1.927256 A:min 9 9 1 0 0 0 1 0 0 0 0 1 0 0
97 109 209.136893 210.216621 1.079728 F#:hdim7 6 6 1 0 0 0 1 0 1 0 0 1 0 0
98 109 210.216621 211.656258 1.439637 G 7 7 0 0 1 0 0 0 0 1 0 0 0 1
99 109 211.656258 213.107505 1.451247 B:min 11 11 0 0 1 0 0 0 1 0 0 0 0 1
100 109 213.107505 214.616802 1.509297 E:min7 4 4 0 0 1 0 1 0 0 1 0 0 0 1
101 109 214.616802 216.068049 1.451247 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
102 109 216.068049 217.554126 1.486077 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
103 109 217.554126 218.993764 1.439638 F 5 5 1 0 0 0 0 1 0 0 0 1 0 0
104 109 218.993764 220.491451 1.497687 E:min 4 4 0 0 0 0 1 0 0 1 0 0 0 1
105 109 220.491451 221.942698 1.451247 E:min7/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 1
106 109 221.942698 224.856802 2.914104 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
107 109 224.856802 226.354489 1.497687 C 0 0 1 0 0 0 1 0 0 1 0 0 0 0
108 109 226.354489 227.782517 1.428028 F#:(1,4,b5) 6 6 1 0 0 0 0 0 1 0 0 0 0 1
109 109 227.782517 229.245374 1.462857 E:min/b3 4 7 0 0 0 0 1 0 0 1 0 0 0 1
110 109 229.245374 230.719841 1.474467 A:min(2) 9 9 1 0 0 0 1 0 0 0 0 1 0 1
111 109 230.719841 232.136258 1.416417 E:min(*b3)/5 4 11 0 0 0 0 1 0 0 1 0 0 0 1
112 109 232.136258 233.564285 1.428027 C:maj7(*5) 0 0 1 0 0 0 1 0 0 0 0 0 0 1
113 109 233.564285 234.992312 1.428027 E:min7(*5)/b7 4 2 0 0 1 0 1 0 0 1 0 0 0 0
114 109 234.992312 241.336491 6.344179 E:(1,2,5,b6) 4 4 1 0 0 0 1 0 1 0 0 0 0 1
115 109 241.336491 259.316098 17.979607 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
116 109 259.316098 261.154269 1.838171 E:(1) 4 4 0 0 0 0 1 0 0 0 0 0 0 0
117 109 261.154269 303.623671 42.469402 E 4 4 0 0 0 0 1 0 0 0 1 0 0 1
118 109 303.623671 306.859617 3.235946 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0
119 109 306.859617 333.792653 26.933036 N 0 0 0 0 0 0 0 0 0 0 0 0 0 0

120 rows × 19 columns


In [51]:
chord = chords.iloc[0]
keys_for_track = keys[keys['track_id'] == chord.track_id]
keys_for_track[keys_for_track['start'] >= chord['start']]


Out[51]:
track_id start end duration key_indicator key_label key_diatonic_root_label key_diatonic_root
0 0 0.000 1.035 1.035 Silence NaN None NaN
1 0 1.035 171.880 170.845 Key E E 4
2 0 171.880 175.800 3.920 Silence NaN None NaN

In [52]:
# this is very inefficient, it takes many seconds
# TODO: optimize this!
key_labels_for_chords = chords[['track_id','start']].apply(
    lambda row: find_key(keys, row['track_id'], row['start']),
    axis=1)[['key_diatonic_root_label', 'key_diatonic_root']]

In [53]:
key_labels_for_chords[:10]


Out[53]:
key_diatonic_root_label key_diatonic_root
0 None NaN
1 E 4
2 E 4
3 E 4
4 E 4
5 E 4
6 E 4
7 E 4
8 E 4
9 E 4

Append the computed key for each chord segment.


In [54]:
for col in ('key_diatonic_root_label', 'key_diatonic_root'):
    chords[col] = key_labels_for_chords[col]

In [55]:
chords


Out[55]:
track_id start end duration label root bass C Db D ... E F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root
0 0 0.000000 2.612267 2.612267 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None NaN
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
5 0 20.410362 21.908049 1.497687 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
6 0 21.908049 23.370907 1.462858 E:7/3 4 8 0 0 1 ... 1 0 0 0 1 0 0 1 E 4
7 0 23.370907 24.856984 1.486077 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
8 0 24.856984 26.343061 1.486077 A:min/b3 9 0 1 0 0 ... 1 0 0 0 0 1 0 0 E 4
9 0 26.343061 27.840748 1.497687 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
10 0 27.840748 29.350045 1.509297 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
11 0 29.350045 35.305963 5.955918 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
12 0 35.305963 36.803650 1.497687 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
13 0 36.803650 41.263102 4.459452 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
14 0 41.263102 44.245646 2.982544 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
15 0 44.245646 45.720113 1.474467 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
16 0 45.720113 47.206190 1.486077 E:7/3 4 8 0 0 1 ... 1 0 0 0 1 0 0 1 E 4
17 0 47.206190 48.692267 1.486077 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
18 0 48.692267 50.155124 1.462857 A:min/b3 9 0 1 0 0 ... 1 0 0 0 0 1 0 0 E 4
19 0 50.155124 51.652811 1.497687 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
20 0 51.652811 53.138888 1.486077 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
21 0 53.138888 56.111043 2.972155 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
22 0 56.111043 65.131995 9.020952 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
23 0 65.131995 68.150589 3.018594 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
24 0 68.150589 71.192403 3.041814 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
25 0 71.192403 74.199387 3.006984 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
26 0 74.199387 75.697074 1.497687 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
27 0 75.697074 80.236575 4.539501 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
28 0 80.236575 83.208730 2.972155 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
29 0 83.208730 86.221693 3.012963 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
54 179 120.053537 122.004013 1.950476 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
55 179 122.004013 122.967641 0.963628 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
56 179 122.967641 123.942879 0.975238 G/2 7 9 0 0 1 ... 0 0 0 1 0 1 0 1 D 2
57 179 123.942879 127.843832 3.900953 A:7 9 9 0 1 0 ... 1 0 0 1 0 1 0 0 D 2
58 179 127.843832 129.805918 1.962086 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
59 179 129.805918 130.792766 0.986848 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
60 179 130.792766 131.245555 0.452789 G/2 7 9 0 0 1 ... 0 0 0 1 0 1 0 1 D 2
61 179 131.245555 131.756394 0.510839 D/5 2 9 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
62 179 131.756394 135.622517 3.866123 A:7 9 9 0 1 0 ... 1 0 0 1 0 1 0 0 D 2
63 179 135.622517 137.549773 1.927256 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
64 179 137.549773 139.477029 1.927256 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
65 179 139.477029 143.308321 3.831292 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
66 179 143.308321 145.258798 1.950477 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
67 179 145.258798 146.245646 0.986848 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
68 179 146.245646 146.733265 0.487619 G/2 7 9 0 0 1 ... 0 0 0 1 0 1 0 1 D 2
69 179 146.733265 147.244104 0.510839 D/5 2 9 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
70 179 147.244104 151.110226 3.866122 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
71 179 151.110226 153.060702 1.950476 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
72 179 153.060702 154.024331 0.963629 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
73 179 154.024331 154.523560 0.499229 G/2 7 9 0 0 1 ... 0 0 0 1 0 1 0 1 D 2
74 179 154.523560 155.022789 0.499229 D/5 2 9 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
75 179 155.022789 158.854081 3.831292 A:7 9 9 0 1 0 ... 1 0 0 1 0 1 0 0 D 2
76 179 158.854081 160.781337 1.927256 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
77 179 160.781337 161.489546 0.708209 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 D 2
78 179 161.489546 162.174535 0.684989 G/2 7 9 0 0 1 ... 0 0 0 1 0 1 0 1 D 2
79 179 162.174535 162.696984 0.522449 D/5 2 9 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
80 179 162.696984 166.423786 3.726802 A:7 9 9 0 1 0 ... 1 0 0 1 0 1 0 0 D 2
81 179 166.423786 168.192617 1.768831 D 2 2 0 0 1 ... 0 0 1 0 0 1 0 0 D 2
82 179 168.192617 174.281557 6.088940 D:7 2 2 1 0 1 ... 0 0 1 0 0 1 0 0 D 2
83 179 174.281557 186.984490 12.702933 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 D 2

14621 rows × 21 columns

Key distribution in chord segments.


In [56]:
chords.key_diatonic_root_label.value_counts()


Out[56]:
G     2916
A     2528
E     2221
C     2198
D     1928
F      983
B      491
Eb     446
Bb     274
Gb     184
Ab     182
Db      90
dtype: int64

In [57]:
chords.to_csv('data/beatles/derived/all_chords_with_keys.tsv', sep='\t', index=False, float_format='%.6f')

We can see that the key labels are heavily skewed and this might not be good for our ML models.

In order to deskew the class distribution we can generate more data from the existing data by transposing each data point to all 12 keys. This way we'll have a 12x larger dataset and uniform classes.


In [58]:
chords.head()


Out[58]:
track_id start end duration label root bass C Db D ... E F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root
0 0 0.000000 2.612267 2.612267 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 None NaN
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4

5 rows × 21 columns


In [139]:
def add_pitch_classes(a, b):
    return ((a + b) + 12) % 12

def rotate_columns(cols, shift):
    return cols[shift:] + cols[:shift]

pcs_columns = ['C','Db','D','Eb','E','F','Gb','G','Ab','A','Bb','B']

[rotate_columns(pcs_columns, i) for i in range(12)]


Out[139]:
[['C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B'],
 ['Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C'],
 ['D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db'],
 ['Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D'],
 ['E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb'],
 ['F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E'],
 ['Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F'],
 ['G', 'Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb'],
 ['Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G'],
 ['A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab'],
 ['Bb', 'B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A'],
 ['B', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb']]

In [84]:
def rotate_binary_pcs_cols(df, cols, shift):
    return df.rename_axis(dict(zip(cols, rotate_columns(cols, shift))), axis=1)
    
rotate_binary_pcs_cols(chords, pcs_columns, 2)[pcs_columns].head()


Out[84]:
C Db D Eb E F Gb G Ab A Bb B
0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 1 0 0 0 1 0
2 0 0 0 1 0 0 1 0 0 0 0 1
3 0 1 0 0 0 0 1 0 0 0 1 0
4 0 1 0 0 0 1 0 0 1 0 0 0

In [61]:
chords[pcs_columns].head()


Out[61]:
C Db D Eb E F Gb G Ab A Bb B
0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 0 0 0 1 0 0 0 1 0 0 1
2 0 1 0 0 1 0 0 0 0 1 0 0
3 0 0 0 0 1 0 0 0 1 0 0 1
4 0 0 0 1 0 0 1 0 0 0 0 1

In [62]:
def transpose_col(df, shift):
    return df.apply(lambda pc: add_pitch_classes(pc, shift))

transpose_col(chords[['root', 'bass', 'key_diatonic_root']], 11).head()


Out[62]:
root bass key_diatonic_root
0 11 11 NaN
1 3 3 3
2 8 8 3
3 3 3 3
4 10 10 3

In [63]:
def transpose_chords_df(chords, shift):
    chords_copy = chords.copy()
    chords_copy['synth_transposition'] = shift
    pc_cols = ['root', 'bass', 'key_diatonic_root']
    chords_copy[pc_cols] = transpose_col(chords_copy[pc_cols], shift)
    chords_copy['key_diatonic_root_label'] = chords_copy['key_diatonic_root'].apply(label_for_pitch_class)
    chords_copy = rotate_binary_pcs_cols(chords_copy, pcs_columns, shift)
    chords_copy = chords_copy.rename_axis({'label': 'orig_chord_label'}, axis=1)
    return chords_copy

transpose_chords_df(chords, 1).head()


Out[63]:
track_id start end duration orig_chord_label root bass Db D Eb ... Gb G Ab A Bb B C key_diatonic_root_label key_diatonic_root synth_transposition
0 0 0.000000 2.612267 2.612267 N 1 1 0 0 0 ... 0 0 0 0 0 0 0 None NaN 1
1 0 2.612267 11.459070 8.846803 E 5 5 0 0 0 ... 0 0 0 1 0 0 1 F 5 1
2 0 11.459070 12.921927 1.462857 A 10 10 0 1 0 ... 0 0 0 0 1 0 0 F 5 1
3 0 12.921927 17.443474 4.521547 E 5 5 0 0 0 ... 0 0 0 1 0 0 1 F 5 1
4 0 17.443474 20.410362 2.966888 B 0 0 0 0 0 ... 0 1 0 0 0 0 1 F 5 1

5 rows × 22 columns


In [93]:
def generate_transpositions(chords):
    df = pd.concat([transpose_chords_df(chords, shift) for shift in range(12)])
    df = df[['track_id', 'synth_transposition',
             'start', 'end', 'duration',
             'orig_chord_label', 'root', 'bass',
             'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B',
             'key_diatonic_root_label', 'key_diatonic_root']]
    return df

In [94]:
chords_all_synth = generate_transpositions(chords)

In [95]:
chords_all_synth.columns


Out[95]:
Index(['track_id', 'synth_transposition', 'start', 'end', 'duration', 'orig_chord_label', 'root', 'bass', 'C', 'Db', 'D', 'Eb', 'E', 'F', 'Gb', 'G', 'Ab', 'A', 'Bb', 'B', 'key_diatonic_root_label', 'key_diatonic_root'], dtype='object')

In [96]:
len(chords_all_synth)


Out[96]:
175452

All key classes are now of uniform probability.


In [97]:
chords_all_synth['key_diatonic_root'].value_counts()


Out[97]:
11    14441
10    14441
9     14441
8     14441
7     14441
6     14441
5     14441
4     14441
3     14441
2     14441
1     14441
0     14441
dtype: int64

In [98]:
chords_all_synth[pcs_columns].mean()


Out[98]:
C     0.257164
Db    0.257164
D     0.257164
Eb    0.257164
E     0.257164
F     0.257164
Gb    0.257164
G     0.257164
Ab    0.257164
A     0.257164
Bb    0.257164
B     0.257164
dtype: float64

In [99]:
chords_all_synth.head()


Out[99]:
track_id synth_transposition start end duration orig_chord_label root bass C Db ... E F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root
0 0 0 0.000000 2.612267 2.612267 N 0 0 0 0 ... 0 0 0 0 0 0 0 0 None NaN
1 0 0 2.612267 11.459070 8.846803 E 4 4 0 0 ... 1 0 0 0 1 0 0 1 E 4
2 0 0 11.459070 12.921927 1.462857 A 9 9 0 1 ... 1 0 0 0 0 1 0 0 E 4
3 0 0 12.921927 17.443474 4.521547 E 4 4 0 0 ... 1 0 0 0 1 0 0 1 E 4
4 0 0 17.443474 20.410362 2.966888 B 11 11 0 0 ... 0 0 1 0 0 0 0 1 E 4

5 rows × 22 columns


In [100]:
chords_all_synth[abs(chords_all_synth['start'] - 2.612267) < 1e-3]


Out[100]:
track_id synth_transposition start end duration orig_chord_label root bass C Db ... E F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root
1 0 0 2.612267 11.45907 8.846803 E 4 4 0 0 ... 1 0 0 0 1 0 0 1 E 4
1 0 1 2.612267 11.45907 8.846803 E 5 5 1 0 ... 0 1 0 0 0 1 0 0 F 5
1 0 2 2.612267 11.45907 8.846803 E 6 6 0 1 ... 0 0 1 0 0 0 1 0 Gb 6
1 0 3 2.612267 11.45907 8.846803 E 7 7 0 0 ... 0 0 0 1 0 0 0 1 G 7
1 0 4 2.612267 11.45907 8.846803 E 8 8 1 0 ... 0 0 0 0 1 0 0 0 Ab 8
1 0 5 2.612267 11.45907 8.846803 E 9 9 0 1 ... 1 0 0 0 0 1 0 0 A 9
1 0 6 2.612267 11.45907 8.846803 E 10 10 0 0 ... 0 1 0 0 0 0 1 0 Bb 10
1 0 7 2.612267 11.45907 8.846803 E 11 11 0 0 ... 0 0 1 0 0 0 0 1 B 11
1 0 8 2.612267 11.45907 8.846803 E 0 0 1 0 ... 1 0 0 1 0 0 0 0 C 0
1 0 9 2.612267 11.45907 8.846803 E 1 1 0 1 ... 0 1 0 0 1 0 0 0 Db 1
1 0 10 2.612267 11.45907 8.846803 E 2 2 0 0 ... 0 0 1 0 0 1 0 0 D 2
1 0 11 2.612267 11.45907 8.846803 E 3 8 0 0 ... 0 0 0 1 0 0 1 0 Eb 3

12 rows × 22 columns


In [101]:
chords_all_synth.to_csv('data/beatles/derived/all_chords_with_keys_synth.tsv', sep='\t', index=False, float_format='%.6f')

Chord sequences


In [247]:
chords_all = pd.read_csv('data/beatles/derived/all_chords_with_keys.tsv', sep='\t')
chords_all_synth = pd.read_csv('data/beatles/derived/all_chords_with_keys_synth.tsv', sep='\t')

In [248]:
chords_all = chords_all.dropna()
chords_all_synth = chords_all_synth.dropna()
chords_all.head()


Out[248]:
track_id start end duration label root bass C Db D ... E F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 ... 1 0 0 0 0 1 0 0 E 4
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 ... 0 0 1 0 0 0 0 1 E 4
5 0 20.410362 21.908049 1.497687 E 4 4 0 0 0 ... 1 0 0 0 1 0 0 1 E 4

5 rows × 21 columns


In [98]:
track_chords = chords_all[(chords_all['track_id'] == 40)].copy()
track_chords.head(10)


Out[98]:
track_id start end duration label root bass C Db D ... F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root key_index
2976 40 0.000000 0.421247 0.421247 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 A 9 53
2977 40 0.421247 1.148857 0.727610 F#:(1,4,b7) 6 6 0 0 0 ... 0 1 0 0 0 0 1 A 9 53
2978 40 1.148857 4.997527 3.848670 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 A 9 53
2979 40 4.997527 7.053628 2.056101 A:min 9 9 1 0 0 ... 0 0 0 0 1 0 0 A 9 53
2980 40 7.053628 8.899614 1.845986 G 7 7 0 0 1 ... 0 0 1 0 0 0 1 C 0 54
2981 40 8.899614 10.873310 1.973696 F 5 5 1 0 0 ... 1 0 0 0 1 0 0 C 0 54
2982 40 10.873310 12.742517 1.869207 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 C 0 54
2983 40 12.742517 16.538979 3.796462 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 C 0 54
2984 40 16.538979 18.477845 1.938866 A:min 9 9 1 0 0 ... 0 0 0 0 1 0 0 A 9 55
2985 40 18.477845 20.347052 1.869207 G 7 7 0 0 1 ... 0 0 1 0 0 0 1 C 0 56

10 rows × 22 columns


In [62]:
chords_all['key_index'] = ((chords_all['key_diatonic_root'].diff() != 0) | (chords_all['track_id'].diff() != 0)).cumsum()

In [63]:
chords_all


Out[63]:
track_id start end duration label root bass C Db D ... F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root key_index
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
5 0 20.410362 21.908049 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
6 0 21.908049 23.370907 1.462858 E:7/3 4 8 0 0 1 ... 0 0 0 1 0 0 1 E 4 1
7 0 23.370907 24.856984 1.486077 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
8 0 24.856984 26.343061 1.486077 A:min/b3 9 0 1 0 0 ... 0 0 0 0 1 0 0 E 4 1
9 0 26.343061 27.840748 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
10 0 27.840748 29.350045 1.509297 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
11 0 29.350045 35.305963 5.955918 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
12 0 35.305963 36.803650 1.497687 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
13 0 36.803650 41.263102 4.459452 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
14 0 41.263102 44.245646 2.982544 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
15 0 44.245646 45.720113 1.474467 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
16 0 45.720113 47.206190 1.486077 E:7/3 4 8 0 0 1 ... 0 0 0 1 0 0 1 E 4 1
17 0 47.206190 48.692267 1.486077 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
18 0 48.692267 50.155124 1.462857 A:min/b3 9 0 1 0 0 ... 0 0 0 0 1 0 0 E 4 1
19 0 50.155124 51.652811 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
20 0 51.652811 53.138888 1.486077 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
21 0 53.138888 56.111043 2.972155 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
22 0 56.111043 65.131995 9.020952 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
23 0 65.131995 68.150589 3.018594 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
24 0 68.150589 71.192403 3.041814 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
25 0 71.192403 74.199387 3.006984 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
26 0 74.199387 75.697074 1.497687 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
27 0 75.697074 80.236575 4.539501 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
28 0 80.236575 83.208730 2.972155 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
29 0 83.208730 86.221693 3.012963 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
30 0 86.221693 87.736621 1.514928 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
14591 179 120.053537 122.004013 1.950476 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14592 179 122.004013 122.967641 0.963628 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14593 179 122.967641 123.942879 0.975238 G/2 7 9 0 0 1 ... 0 0 1 0 1 0 1 D 2 249
14594 179 123.942879 127.843832 3.900953 A:7 9 9 0 1 0 ... 0 0 1 0 1 0 0 D 2 249
14595 179 127.843832 129.805918 1.962086 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14596 179 129.805918 130.792766 0.986848 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14597 179 130.792766 131.245555 0.452789 G/2 7 9 0 0 1 ... 0 0 1 0 1 0 1 D 2 249
14598 179 131.245555 131.756394 0.510839 D/5 2 9 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14599 179 131.756394 135.622517 3.866123 A:7 9 9 0 1 0 ... 0 0 1 0 1 0 0 D 2 249
14600 179 135.622517 137.549773 1.927256 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14601 179 137.549773 139.477029 1.927256 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14602 179 139.477029 143.308321 3.831292 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14603 179 143.308321 145.258798 1.950477 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14604 179 145.258798 146.245646 0.986848 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14605 179 146.245646 146.733265 0.487619 G/2 7 9 0 0 1 ... 0 0 1 0 1 0 1 D 2 249
14606 179 146.733265 147.244104 0.510839 D/5 2 9 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14607 179 147.244104 151.110226 3.866122 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14608 179 151.110226 153.060702 1.950476 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14609 179 153.060702 154.024331 0.963629 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14610 179 154.024331 154.523560 0.499229 G/2 7 9 0 0 1 ... 0 0 1 0 1 0 1 D 2 249
14611 179 154.523560 155.022789 0.499229 D/5 2 9 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14612 179 155.022789 158.854081 3.831292 A:7 9 9 0 1 0 ... 0 0 1 0 1 0 0 D 2 249
14613 179 158.854081 160.781337 1.927256 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14614 179 160.781337 161.489546 0.708209 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 D 2 249
14615 179 161.489546 162.174535 0.684989 G/2 7 9 0 0 1 ... 0 0 1 0 1 0 1 D 2 249
14616 179 162.174535 162.696984 0.522449 D/5 2 9 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14617 179 162.696984 166.423786 3.726802 A:7 9 9 0 1 0 ... 0 0 1 0 1 0 0 D 2 249
14618 179 166.423786 168.192617 1.768831 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 249
14619 179 168.192617 174.281557 6.088940 D:7 2 2 1 0 1 ... 0 1 0 0 1 0 0 D 2 249
14620 179 174.281557 186.984490 12.702933 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 D 2 249

14441 rows × 22 columns


In [96]:
# track_chords.groupby(['track_id']).last()['key_index']
(chords_all.groupby(['track_id', 'key_index']).count()['start'] > 16).mean()


Out[96]:
0.76305220883534142

In [222]:
c = chords_all[:200]
c


Out[222]:
track_id start end duration label root bass C Db D ... F Gb G Ab A Bb B key_diatonic_root_label key_diatonic_root key_index
1 0 2.612267 11.459070 8.846803 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
2 0 11.459070 12.921927 1.462857 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
3 0 12.921927 17.443474 4.521547 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
4 0 17.443474 20.410362 2.966888 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
5 0 20.410362 21.908049 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
6 0 21.908049 23.370907 1.462858 E:7/3 4 8 0 0 1 ... 0 0 0 1 0 0 1 E 4 1
7 0 23.370907 24.856984 1.486077 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
8 0 24.856984 26.343061 1.486077 A:min/b3 9 0 1 0 0 ... 0 0 0 0 1 0 0 E 4 1
9 0 26.343061 27.840748 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
10 0 27.840748 29.350045 1.509297 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
11 0 29.350045 35.305963 5.955918 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
12 0 35.305963 36.803650 1.497687 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
13 0 36.803650 41.263102 4.459452 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
14 0 41.263102 44.245646 2.982544 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
15 0 44.245646 45.720113 1.474467 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
16 0 45.720113 47.206190 1.486077 E:7/3 4 8 0 0 1 ... 0 0 0 1 0 0 1 E 4 1
17 0 47.206190 48.692267 1.486077 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
18 0 48.692267 50.155124 1.462857 A:min/b3 9 0 1 0 0 ... 0 0 0 0 1 0 0 E 4 1
19 0 50.155124 51.652811 1.497687 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
20 0 51.652811 53.138888 1.486077 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
21 0 53.138888 56.111043 2.972155 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
22 0 56.111043 65.131995 9.020952 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
23 0 65.131995 68.150589 3.018594 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
24 0 68.150589 71.192403 3.041814 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
25 0 71.192403 74.199387 3.006984 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
26 0 74.199387 75.697074 1.497687 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
27 0 75.697074 80.236575 4.539501 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
28 0 80.236575 83.208730 2.972155 B 11 11 0 0 0 ... 0 1 0 0 0 0 1 E 4 1
29 0 83.208730 86.221693 3.012963 E 4 4 0 0 0 ... 0 0 0 1 0 0 1 E 4 1
30 0 86.221693 87.736621 1.514928 A 9 9 0 1 0 ... 0 0 0 0 1 0 0 E 4 1
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
174 2 157.240183 159.480454 2.240271 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 3
175 2 159.480454 161.624986 2.144532 B:min 11 11 0 0 1 ... 0 1 0 0 0 0 1 D 2 3
176 2 161.624986 163.941847 2.316861 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 3
177 2 163.941847 165.990642 2.048795 B:min 11 11 0 0 1 ... 0 1 0 0 0 0 1 D 2 3
178 2 165.990642 168.173469 2.182827 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 3
179 2 168.173469 170.528625 2.355156 B:min 11 11 0 0 1 ... 0 1 0 0 0 0 1 D 2 3
180 2 170.528625 174.530476 4.001851 D 2 2 0 0 1 ... 0 1 0 0 1 0 0 D 2 3
182 3 0.000000 0.459543 0.459543 N 0 0 0 0 0 ... 0 0 0 0 0 0 0 Bb 10 4
183 3 0.459543 7.639897 7.180354 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
184 3 7.639897 14.977403 7.337506 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
185 3 14.977403 18.646156 3.668753 Eb:7 3 3 0 1 0 ... 0 0 1 0 0 1 0 Bb 10 4
186 3 18.646156 22.338129 3.691973 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
187 3 22.338129 24.184115 1.845986 F:9 5 5 1 0 0 ... 1 0 1 0 1 0 0 Bb 10 4
188 3 24.184115 26.041712 1.857597 Eb:9 3 3 0 1 0 ... 1 0 1 0 0 1 0 Bb 10 4
189 3 26.041712 27.910918 1.869206 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
190 3 27.910918 29.780124 1.869206 F 5 5 1 0 0 ... 1 0 0 0 1 0 0 Bb 10 4
191 3 29.780124 37.106020 7.325896 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
192 3 37.106020 40.797993 3.691973 Eb:7 3 3 0 1 0 ... 0 0 1 0 0 1 0 Bb 10 4
193 3 40.797993 44.466746 3.668753 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
194 3 44.466746 46.324342 1.857596 F:9 5 5 1 0 0 ... 1 0 1 0 1 0 0 Bb 10 4
195 3 46.324342 48.170328 1.845986 Eb:9 3 3 0 1 0 ... 1 0 1 0 0 1 0 Bb 10 4
196 3 48.170328 49.981485 1.811157 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
197 3 49.981485 51.839081 1.857596 Bb:7 10 10 0 0 1 ... 1 0 0 1 0 1 0 Bb 10 4
198 3 51.839081 55.589104 3.750023 Eb 3 3 0 0 0 ... 0 0 1 0 0 1 0 Bb 10 4
199 3 55.589104 59.292687 3.703583 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
200 3 59.292687 63.042709 3.750022 Eb 3 3 0 0 0 ... 0 0 1 0 0 1 0 Bb 10 4
201 3 63.042709 66.734682 3.691973 F 5 5 1 0 0 ... 1 0 0 0 1 0 0 Bb 10 4
202 3 66.734682 74.118628 7.383946 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4
203 3 74.118628 77.857040 3.738412 Eb:7 3 3 0 1 0 ... 0 0 1 0 0 1 0 Bb 10 4
204 3 77.857040 81.525793 3.668753 Bb 10 10 0 0 1 ... 1 0 0 0 0 1 0 Bb 10 4

200 rows × 22 columns


In [217]:
def pcs_block_cols(block_size):
    return ['%s_%02d'%(pc, i) for i in range(block_size) for pc in pcs_columns]

def block_columns(block_size): 
    return pcs_block_cols(block_size) + ['key_diatonic_root']

def merge_chord_block(block_df):
    all_pcs = block_df.as_matrix(columns=pcs_columns).ravel()
    most_frequent_key = block_df['key_diatonic_root'].value_counts().index[0]
    return np.hstack([all_pcs, most_frequent_key])

In [252]:
def roll_chords(chords_df, window_size=4):
    blocks = (chords_df.iloc[start:start+window_size] for start in range(len(chords_df) - window_size + 1))
    c_rolling = (merge_chord_block(block) for block in blocks)
    df_rolling = pd.DataFrame(c_rolling, columns=block_columns(window_size)).astype(np.int16)
    return df_rolling

Generate data points by reshaping input rows in the rolling window and selecting the most frequent output label. Do this for both original and synthetic data and for a different window sizes.


In [256]:
# TODO: optimize this, since it is not really efficient (~20 minutes for all the files...)

In [254]:
for postfix, chords in [('', chords_all), ('_synth', chords_all_synth)]:
    for window in (1,2,4,8,16):
        print('window:', window)
        chords_rolling = roll_chords(chords, window_size=window)
        print('shape:', chords_rolling.shape)
        chords_rolling.to_csv('data/beatles/derived/all_chords_with_keys'+postfix+'_rolling_'+str(window)+'.tsv', sep='\t', index=False)


window: 1
shape: (14441, 13)
window: 2
shape: (14440, 25)
window: 4
shape: (14438, 49)
window: 8
shape: (14434, 97)
window: 16
shape: (14426, 193)
window: 1
shape: (173292, 13)
window: 2
shape: (173291, 25)
window: 4
shape: (173289, 49)
window: 8
shape: (173285, 97)
window: 16
shape: (173277, 193)

In [ ]: