Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Engineering Pop Songs with Python

Engineering Pop Songs with Python

Christian Weber

February 17, 2019
Tweet

More Decks by Christian Weber

Other Decks in Programming

Transcript

  1. whoami @classicwebdog • If you don’t know python/music, you’ll learn

    something new • If you know python/music, consider this a refresher • I’ll learn something from you
  2. Key takeaways for today @classicwebdog • The art of the

    possible • Learn stuff about python • Learn some music theory!
  3. Major Scale - The equation 1/2 T 1/2 T S

    1/2 T 1/2 T 1/2 T S I/Root 2 3 4 5 6 7 Octave C C# D D# E F F# G G# A A# B C G G# A A# B C C# D D# E F F# G R, T, T, S, T, T, T, S @classicwebdog
  4. Chords in the major scale 1 2 3 4 5

    6 7 Chord C D E F G A B CMaj D E F G A B C Dmin E F G A B C D Emin F G A B C D E FMaj G A B C D E F GMaj A B C D E F G Amin B C D E F G A Bdim @classicwebdog
  5. Express Yourself print("I really love The Beatles" >>> “I really

    love The Beatles” def fav_band(band): return f'My favorite band is {band}' fav_band("The Beatles”) >>>My favorite band is The Beatles @classicwebdog
  6. Representing and Structuring Data strings = "Hey ho let's go"

    strings.split(" ") # ["Hey", "Ho", "let's", "go"] beatles_songs = ["Let it Be", "Yesterday", "I wanna hold your hand"] song = lists[0] # "Let it Be” song = lists[-1] # “I wanna hold your hand” michael_jackson = ("Thriller", "Beat It", "You are not alone") mj_songs = michael_jackson[-1] # Nope! Doesn’t work! Why? best_punk_bands_by_year = { 1993: "Green Day", 1994: "Rancid", 1995: "Blink 182", 1996: "Mighty Mighty Bosstones" } best_punk_bands_by_year[1993] # Green Day best_punk_bands_by_year.keys() # dict_keys([1993, 1994, 1995, 1996]) @classicwebdog
  7. How can we execute certain code? def time_signature(time_sig): if time_sig

    == 4: print("We're going to play in 4/4 time") return True elif time_sig == 3: print("We're going to play in 3/4 time") return True else: print("Unsupported time signature!") return False @classicwebdog
  8. How can we represent `things`? • First we had data

    types • Then we talked about conditionals • Moving on to functions • Can we go higher? Yes! @classicwebdog
  9. Class with Inheritance class Notes(object): notes = ["C","C#/Db","D","D#/Eb","E","F","F#/Gb","G","G#/Ab","A","A#/Bb","B"] def calculate_total_notes(self):

    return len(self.notes) class Music(Notes): def __init__(self, scale): self.scale = scale def major(self): if self.scale == "major": scale_list = [] for note in self.notes: if "/" in note: pass else: scale_list.append(note) return scale_list else: return None @classicwebdog
  10. metaclasses and dunder methods @classicwebdog class Notes(object): notes = ["C","C#/Db","D","D#/Eb","E","F","F#/Gb","G","G#/Ab","A","A#/Bb","B"]

    def calculate_total_notes(self): return len(self.notes) class Music(Notes): def __init__(self, scale): self.scale = scale def __str__(self): return f'Class for the {self.scale} scale. Also has these notes from the chromatic scale: {self.notes}' def __repr__(self): return f'<Music for the {self.scale}>' def major(self): if self.scale == "major": scale_list = [] for note in self.notes: if "/" in note: pass else: scale_list.append(note) return scale_list else: return None
  11. Chord Progressions = More structure @classicwebdog 1 2 3 4

    5 6 7 Chord C D E F G A B CMaj D E F G A B C Dmin E F G A B C D Emin F G A B C D E FMaj G A B C D E F GMaj A B C D E F G Amin B C D E F G A Bdim
  12. Chord Progressions = More structure @classicwebdog 1 2 3 4

    5 6 7 Chord C D E F G A B CMaj I D E F G A B C Dmin ii E F G A B C D Emin iii F G A B C D E FMaj IV G A B C D E F GMaj V A B C D E F G Amin vi B C D E F G A Bdim vii
  13. How are songs typically structured? @classicwebdog • Verse (8 bars)

    • Chorus (4 bars) • Verse (8 bars) • Chorus (4 bars)
  14. Generating “random” lyrics @classicwebdog import random class Lyrics(object): adjective =

    ["everyday", "sometimes", "occasionally", "significantly", "excited"] verbs = ["excuse", "absorb", "kiss", "drop", "isolate", "fling"] nouns = ["head", "heart", "skin", "air", "chair", "carpet"] adverbs = ["dutifully", "crazily", "realistically", "heartfully", "foolishly"] contractions = ["don't", "can't", "won't", "hasn't", "must've"] identifier = ["I", "She", "He", "They", "We"] def random_verse(self, bars=8): verses = [] for i in range(bars): random_num = random.randrange(0, len(self.adjective)) rand_verse = self.identifier[random_num] + ' ' + self.contractions[random_num] + ' ' + self.adverbs[random_num] +' ' + self.nouns[random_num] + ' ' + self.verbs[random_num] + ' ' + self.adjective[random_num] verses.append(rand_verse) return verses
  15. Generating the progression @classicwebdog import random class Song(Music): def __init__(self,

    progression): self.progression = progression def is_pop(self): if self.progression == "pop": notes = self.major() prog_dict = {} for note in notes: if note == "C": prog_dict["CMaj"] = 1 elif note == "F": prog_dict["FMaj"] = 4 elif note == "G": prog_dict["GMaj"] == 5 elif note == "A": prog_dict["Amin"] == 6 else: pass return prog_dict else: return None
  16. Represented as code @classicwebdog c = l.random_chorus() chords = [keys

    for keys in s.is_pop()] for i in l.random_verse(): r = random.randrange(0, len(chords)) print(chords[r]) print(i) print("\n") for i in c: print(chords[0], chords[1], chords[2], chords[3]) print(i) print("\n") for i in l.random_verse(): r = random.randrange(0, len(chords)) print(chords[r]) print(i) print("\n") for i in c: print(i)
  17. Outputs some…interesting results @classicwebdog FMaj They hasn't heartfully air drop

    significantly GMaj They hasn't heartfully air drop significantly CMaj She can't crazily heart absorb sometimes FMaj They hasn't heartfully air drop significantly CMaj She can't crazily heart absorb sometimes Amin They hasn't heartfully air drop significantly GMaj He won't realistically skin kiss occasionally GMaj She can't crazily heart absorb sometimes CMaj FMaj GMaj Amin We must've foolishly chair isolate excited CMaj FMaj GMaj Amin We must've foolishly chair isolate excited CMaj FMaj GMaj Amin We must've foolishly chair isolate excited CMaj FMaj GMaj Amin We must've foolishly chair isolate excited GMaj I don't dutifully head excuse everyday Amin I don't dutifully head excuse everyday FMaj We must've foolishly chair isolate excited GMaj He won't realistically skin kiss occasionally Amin I don't dutifully head excuse everyday GMaj I don't dutifully head excuse everyday GMaj She can't crazily heart absorb sometimes GMaj They hasn't heartfully air drop significantly We must've foolishly chair isolate excited We must've foolishly chair isolate excited We must've foolishly chair isolate excited We must've foolishly chair isolate excited
  18. Next time… @classicwebdog • How could we get this into

    a testable format? • Could we dynamically re-engineer a MIDI like this? • Who is going to sing the crazy lyrics?