Advanced Functional Programming in Industry
Advanced Functional Programming in Industry
Jos
e Pedro Magalh
aes
1 / 46
Introduction
I
I
I
I
I
Jos
e Pedro Magalh
aes
Musical analysis
Finding cover songs
Generating chords and melodies
Correcting errors in chord extraction from audio sources
Chordifya web-based music player with chord recognition
2 / 46
Demo: Chordify
Demo:
http://chordify.net
Jos
e Pedro Magalh
aes
3 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
4 / 46
What is harmony?
SDom
IV
Dom
Ton
Ton
V/V
D7
G7
Harmony arises when at least two notes sound at the same time
Jos
e Pedro Magalh
aes
5 / 46
What is harmony?
SDom
IV
Dom
Ton
Ton
V/V
D7
G7
Harmony arises when at least two notes sound at the same time
Jos
e Pedro Magalh
aes
5 / 46
A chord is built on a root note. So I also stands for the chord built
on the first degree, V for the chord built on the fifth degree, etc.
So the following is a chord sequence: I IV II7 V7 I.
Jos
e Pedro Magalh
aes
6 / 46
So you can start with I, add one note to get I7 , fall into IV, change
two notes to get to II7 , fall into V, and then finally back to I.
Jos
e Pedro Magalh
aes
7 / 46
IV
Dom
Ton
Ton
V/V
D7
G7
Piece
PT
PD
PT
IV
V/V
Jos
e Pedro Magalh
aes
II7
V7
D:7
G:7
8 / 46
Jos
e Pedro Magalh
aes
9 / 46
Jos
e Pedro Magalh
aes
9 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
10 / 46
Why Haskell?
Jos
e Pedro Magalh
aes
11 / 46
Notes
data Root = A | B | C | D | E | F | G
type Octave = Int
data Note = Note Root Octave
Jos
e Pedro Magalh
aes
12 / 46
Notes
data Root = A | B | C | D | E | F | G
type Octave = Int
data Note = Note Root Octave
a4, b4, c4, d4, e4, f4, g4 :: Note
a4 = Note A 4
b4 = Note B 4
c4 = Note C 4
d4 = Note D 4
e4 = Note E 4
f4 = Note F 4
g4 = Note G 4
Jos
e Pedro Magalh
aes
12 / 46
Melody
type Melody = [Note]
cMajScale :: Melody
cMajScale = [c4, d4, e4, f4, g4, a4, b4]
Jos
e Pedro Magalh
aes
13 / 46
Melody
type Melody = [Note]
cMajScale :: Melody
cMajScale = [c4, d4, e4, f4, g4, a4, b4]
cMajScaleRev :: Melody
cMajScaleRev = reverse cMajScale
Jos
e Pedro Magalh
aes
13 / 46
Melody
type Melody = [Note]
cMajScale :: Melody
cMajScale = [c4, d4, e4, f4, g4, a4, b4]
cMajScaleRev :: Melody
cMajScaleRev = reverse cMajScale
reverse :: [] []
reverse [ ]
= []
reverse (h : t) = reverse t +
+ [h]
(+
+) :: [] [] []
(+
+) = . . .
Jos
e Pedro Magalh
aes
13 / 46
Transposition
Jos
e Pedro Magalh
aes
14 / 46
Generation, analysis
Jos
e Pedro Magalh
aes
15 / 46
Generation, analysis
Jos
e Pedro Magalh
aes
15 / 46
Rhythm
Accidentals
Intervals
Voicing
...
Jos
e Pedro Magalh
aes
16 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
17 / 46
PT
S
IV
V/IV
V/I
I7
Vmin
C:7
G:min
ins
S
V/IV
V/I
I7
Vmin
C:7
C:maj
IV
V/V
V7
F:maj
II7
G:7
D:7
G:min
Jos
e Pedro Magalh
aes
18 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
19 / 46
The more similar the trees, the more similar the harmony
Jos
e Pedro Magalh
aes
20 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
21 / 46
# $ " "
%$ " "
"" ""
V III
" "
"" """
"
I III
" "
" "
"" ""
" "
"" ""
" "
II IV
III IV
!
!!!
V
Jos
e Pedro Magalh
aes
22 / 46
Piece
Phrase
Ton
I: Maj
Dom
Sub
Ton
Dom
I: Maj
You can see this tree as having been produced by taking the chords in
green as input. . .
Jos
e Pedro Magalh
aes
23 / 46
Piece
Phrase
Ton
I: Maj
Dom
Sub
Ton
Dom
I: Maj
You can see this tree as having been produced by taking the chords in
green as input. . . or the chords might have been dictated by the structure!
Jos
e Pedro Magalh
aes
23 / 46
Jos
e Pedro Magalh
aes
(M {Maj, Min})
24 / 46
(M {Maj, Min})
Jos
e Pedro Magalh
aes
24 / 46
(M {Maj, Min})
Jos
e Pedro Magalh
aes
24 / 46
(M {Maj, Min})
Jos
e Pedro Magalh
aes
24 / 46
(M {Maj, Min})
DomM
| VM
| VII0M
| SubM DomM
7
| II7M VM
Jos
e Pedro Magalh
aes
SubMaj IIm
Maj
| IVMaj
| IIIm
Maj IVMaj
SubMin IVm
Min
24 / 46
(M {Maj, Min})
DomM
| VM
| VII0M
| SubM DomM
7
| II7M VM
SubMaj IIm
Maj
| IVMaj
| IIIm
Maj IVMaj
SubMin IVm
Min
Jos
e Pedro Magalh
aes
24 / 46
Now in HaskellI
A naive datatype encoding musical harmony:
data Piece = Piece [ Phrase ]
data Phrase where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
Jos
e Pedro Magalh
aes
25 / 46
Now in HaskellI
A naive datatype encoding musical harmony:
data Piece = Piece [ Phrase ]
data Phrase where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
data Ton where
TonMaj :: Degree Ton
TonMin :: Degree Ton
Jos
e Pedro Magalh
aes
25 / 46
Now in HaskellI
A naive datatype encoding musical harmony:
data Piece = Piece [ Phrase ]
data Phrase where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
data Ton where
TonMaj :: Degree Ton
TonMin :: Degree Ton
data Dom where
DomV7 :: Degree Dom
DomV
:: Degree Dom
DomVII0 :: Degree Dom
DomIVV :: SDom Dom Dom
DomIIV :: Degree Degree Dom
Jos
e Pedro Magalh
aes
25 / 46
Now in HaskellI
A naive datatype encoding musical harmony:
data Piece = Piece [ Phrase ]
data Phrase where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
data Ton where
TonMaj :: Degree Ton
TonMin :: Degree Ton
data Dom where
DomV7 :: Degree Dom
DomV
:: Degree Dom
DomVII0 :: Degree Dom
DomIVV :: SDom Dom Dom
DomIIV :: Degree Degree Dom
data Degree = I | II | III . . .
Jos
e Pedro Magalh
aes
25 / 46
Now in HaskellII
A GADT encoding musical harmony:
data Mode = MajMode | MinMode
data Piece ( :: Mode) where
Piece :: [ Phrase ] Piece
Jos
e Pedro Magalh
aes
26 / 46
Now in HaskellII
A GADT encoding musical harmony:
data Mode = MajMode | MinMode
data Piece ( :: Mode) where
Piece :: [ Phrase ] Piece
data Phrase ( :: Mode) where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
Jos
e Pedro Magalh
aes
26 / 46
Now in HaskellII
A GADT encoding musical harmony:
data Mode = MajMode | MinMode
data Piece ( :: Mode) where
Piece :: [ Phrase ] Piece
data Phrase ( :: Mode) where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
data Ton ( :: Mode) where
TonMaj :: SD I Maj Ton MajMode
TonMin :: SD I Min Ton MinMode
Jos
e Pedro Magalh
aes
26 / 46
Now in HaskellII
A GADT encoding musical harmony:
data Mode = MajMode | MinMode
data Piece ( :: Mode) where
Piece :: [ Phrase ] Piece
data Phrase ( :: Mode) where
PhraseIVI :: Ton Dom Ton Phrase
PhraseVI ::
Dom Ton Phrase
data Ton ( :: Mode) where
TonMaj :: SD I Maj Ton MajMode
TonMin :: SD I Min Ton MinMode
data Dom ( :: Mode) where
DomV7 :: SD V Dom7 Dom
DomV
:: SD V Maj Dom
DomVII0 :: SD VII Dim Dom
DomIVV :: SDom Dom Dom
DomIIV :: SD II Dom7 SD V Dom7 Dom
Jos
e Pedro Magalh
aes
26 / 46
Now in HaskellIII
Jos
e Pedro Magalh
aes
27 / 46
Now in HaskellIII
Jos
e Pedro Magalh
aes
27 / 46
Generating harmony
Jos
e Pedro Magalh
aes
28 / 46
Generating harmony
Jos
e Pedro Magalh
aes
28 / 46
Generating harmony
Jos
e Pedro Magalh
aes
28 / 46
Generating harmony
Now that we have a datatype representing harmony sequences, how do
we generate a sequence of chords?
QuickCheck! We give Arbitrary instances for each of the datatypes in our
model.
. . . but we dont want to do this by hand, for every datatype, and to have
to adapt the instances every time we change the model. . . so we use
generic programming:
gen :: .(Representable , Generate (Rep ))
Gen
Jos
e Pedro Magalh
aes
28 / 46
Generating harmony
Now that we have a datatype representing harmony sequences, how do
we generate a sequence of chords?
QuickCheck! We give Arbitrary instances for each of the datatypes in our
model.
. . . but we dont want to do this by hand, for every datatype, and to have
to adapt the instances every time we change the model. . . so we use
generic programming:
gen :: .(Representable , Generate (Rep ))
[ (String,Int) ] Gen
Jos
e Pedro Magalh
aes
28 / 46
Jos
e Pedro Magalh
aes
29 / 46
> example
[C: Maj, D: Dom7 , G: Dom7 , C: Maj]
[C: Maj, G: Dom7 , C: Maj]
[C: Maj, E: Min, F: Maj, G: Maj, C: Maj]
[C: Maj, E: Min, F: Maj, D: Dom7 , G: Dom7 , C: Maj]
[C: Maj, D: Min, E: Min, F: Maj, D: Dom7 , G: Dom7 , C: Maj]
Jos
e Pedro Magalh
aes
29 / 46
Jos
e Pedro Magalh
aes
30 / 46
Jos
e Pedro Magalh
aes
30 / 46
Example I
&
n
?
#
Phrase
Ton
I: Maj
Ton
Dom
Sub
Dom
I: Maj
Jos
e Pedro Magalh
aes
31 / 46
Example II
&
? #
##
#n
Phrase
Ton
I: Min
Dom
Sub
Ton
Dom
Sub
I: Min
Dom
E: Min
Jos
e Pedro Magalh
aes
32 / 46
Table of Contents
Harmony
Haskell
Harmony analysis
Harmonic similarity
Music generation
Chord recognition: Chordify
Jos
e Pedro Magalh
aes
33 / 46
1.00 C
1
0.92 C
0.94 Gm
1.00 G
2
0.96 Em
0.97 C
1.00 Em
3
How to pick the right chord from the chord candidate list? Ask the
harmony model which one fits best.
Jos
e Pedro Magalh
aes
34 / 46
Chordify: architecture
Frontend
I
I
I
I
I
I
Jos
e Pedro Magalh
aes
35 / 46
Chordify: architecture
Frontend
I
I
I
I
I
I
Backend
I
I
I
I
Jos
e Pedro Magalh
aes
35 / 46
Chordify: numbers
Jos
e Pedro Magalh
aes
36 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
Jos
e Pedro Magalh
aes
37 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
Jos
e Pedro Magalh
aes
37 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
Jos
e Pedro Magalh
aes
37 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
I
I
Chordifying new songs takes some computing power, but most songs
are in the database already
Jos
e Pedro Magalh
aes
37 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
I
I
Chordifying new songs takes some computing power, but most songs
are in the database already
Jos
e Pedro Magalh
aes
37 / 46
Single VPS, 6 Intel Xeon cores, 24GB RAM, 500GB SSD, 2TB hard
drive
I
I
Chordifying new songs takes some computing power, but most songs
are in the database already
Jos
e Pedro Magalh
aes
37 / 46
Jos
e Pedro Magalh
aes
38 / 46
I
I
Jos
e Pedro Magalh
aes
38 / 46
I
I
Jos
e Pedro Magalh
aes
1;D:min;0.232199546;0.615328798
2;D:min;0.615328798;0.998458049
...
38 / 46
I
I
1;D:min;0.232199546;0.615328798
2;D:min;0.615328798;0.998458049
...
Jos
e Pedro Magalh
aes
38 / 46
I
I
1;D:min;0.232199546;0.615328798
2;D:min;0.615328798;0.998458049
...
Jos
e Pedro Magalh
aes
38 / 46
Lets have a look at four different online services giving you the chords
for a song (Radioheads Karma Police).
Jos
e Pedro Magalh
aes
39 / 46
Jos
e Pedro Magalh
aes
40 / 46
Jos
e Pedro Magalh
aes
41 / 46
Jos
e Pedro Magalh
aes
42 / 46
Jos
e Pedro Magalh
aes
43 / 46
Jos
e Pedro Magalh
aes
44 / 46
Jos
e Pedro Magalh
aes
44 / 46
I
I
I
I
Jos
e Pedro Magalh
aes
44 / 46
I
I
I
I
Jos
e Pedro Magalh
aes
44 / 46
Summary
Harmonising melodies
Generating harmonies
Jos
e Pedro Magalh
aes
45 / 46
http://chordify.net
http://hackage.haskell.org/package/HarmTrace
http://hackage.haskell.org/package/FComp
Jos
e Pedro Magalh
aes
46 / 46