Slide 1

Slide 1 text

Christian Weber, Senior Solutions Engineer github.com/webdog [email protected] @classicwebdog Engineering Pop Songs with Python

Slide 2

Slide 2 text

whoami @classicwebdog • Python is the best

Slide 3

Slide 3 text

whoami @classicwebdog • I play some instruments

Slide 4

Slide 4 text

whoami @classicwebdog • This was hard!

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Key takeaways for today @classicwebdog • The art of the possible • Learn stuff about python • Learn some music theory!

Slide 7

Slide 7 text

Music @classicwebdog

Slide 8

Slide 8 text

Notes - The Chromatic Scale @classicwebdog

Slide 9

Slide 9 text

How it looks on a piano @classicwebdog

Slide 10

Slide 10 text

Sheet Music - The Structure of Music @classicwebdog

Slide 11

Slide 11 text

Understanding the staff @classicwebdog

Slide 12

Slide 12 text

Let’s see that sheet music again @classicwebdog

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

Python @classicwebdog

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

• Integers • Floats Express Yourself • Booleans • Strings @classicwebdog

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

A single Class 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) @classicwebdog

Slide 22

Slide 22 text

Inheritance @classicwebdog

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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'' 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

Slide 25

Slide 25 text

Python + Music @classicwebdog

Slide 26

Slide 26 text

Joining forces @classicwebdog

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

The most common chord progression of them all @classicwebdog I - V-vi -IV or… C - G - Am - F

Slide 30

Slide 30 text

How are songs typically structured? @classicwebdog • Verse (8 bars) • Chorus (4 bars) • Verse (8 bars) • Chorus (4 bars)

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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)

Slide 34

Slide 34 text

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

Slide 35

Slide 35 text

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?

Slide 36

Slide 36 text

Thanks! @classicwebdog