-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTestFile.Rmd
276 lines (222 loc) · 10.9 KB
/
TestFile.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
---
title: "Test File"
output: pdf_document
---
This file reads in 2 .csv files, one containing a standard major transition matrix and one containing a standard minor key transition matrix. These transition matrices are shifted to all major and minor keys respectively. We then fit transition matrices to new music in the test data and determine its most likely key using our statistical framework.
# Read in Libraries and Set Up Custom Functions
```{r}
library(tidyverse)
library(markovchain)
source('SourceCode.R')
```
# Read in Standard Matrices
```{r}
# Setting Note Parameters
MaxNote = 89
MinNote = 53
G.Major = as.matrix(read.csv("G.Major.csv"))
G.Major = G.Major[,-1]
rownames(G.Major) = c(0,MinNote:MaxNote)
colnames(G.Major) = c(0,MinNote:MaxNote)
G.Major
G.Minor = as.matrix(read.csv("G.Minor.csv"))
G.Minor = G.Minor[,-1]
rownames(G.Minor) = c(0,MinNote:MaxNote)
colnames(G.Minor) = c(0,MinNote:MaxNote)
G.Minor
```
# Create Shift Matrix
```{r}
D = MaxNote-MinNote +2 #Add plus 1 for Zero Row and Plus 1 to make sure both Pitch 52 and 88 have a row
#This means that each MC will have a 36x36 TPM
# Max Note and Min Note defined above
ShiftUp = c(1,rep(0,times = D-1),rep(0,times = D-1),1)
for (k in 1:(D-2)){
newrow = c(rep(0,times = k),1,rep(0,D-k-1))
ShiftUp = c(ShiftUp,newrow)
}
ShiftUp = matrix(data = ShiftUp,nrow = D, byrow = T)
ShiftUp
```
# Read in Test Data
```{r}
# America The Beautiful (in Bb Major)
ATBNotes = c(65,65,62,62,65,65,60,60,62,64,65,67,69,65,65,65,62,62,65,65,60,60,72,71,72,74,67,72,65,74,74,72,70,70,69,69,70,72,69,67,65,70,70,70,67,67,70,70,65,65,65,67,70,65,72,70)
#Happy Birthday (G major)
HBNotesG = c(62,62,64,62,67,66,62,62,64,62,69,67,62,62
,74,71,67,66,64,72,72,71,67,69,67)
#Yankee Doodle (G major)
YDNotesG = c(67,67,69,71,67,71,69,62,67,67,69,71,67,66,67,
67,69,71,72,71,69,67,66,62,64,66,67,67,64,66,
64,62,64,66,67,62,64,62,60,59,62,64,66,64,62,
64,66,67,64,62,67,66,69,67,67)
# This Land is Your Land (F Major)
ThisLand = c(65,67,69,70,70,0,70,65,67,69,69,0,60,65,69,67,67,0,67,67,65,67,69,69,0,65,65,67,69,70,70,0,70,70,65,67,69,69,0,67,67,68,64,60,64,67,65,0,65,67,69,70,70,70,65,65,67,69,69,0,60,65,70,67,67,0,67,65,67,70,70,0,65,67,69,70,70,0,70,65,67,69,69,0,67,67,67,64,60,64,67,65,65,67,69,70,70,0,65,67,69,69,0,60,65,69,67,67,0,67,67,65,67,69,69,0,65,65,67,69,70,70,0,70,70,65,67,69,69,0,67,67,68,64,60,64,67,65,0,65,67,69,70,70,0,65,67,69,69,0,60,65,69,67,67,0,67,67,65,67,69,69,0,65,65,67,69,70,70,0,70,70,65,67,69,69,0,67,67,68,64,60,64,67,65,0,65,67,69,70,70,70,65,65,67,69,69,0,60,65,70,67,67,0,67,65,67,70,70,0,65,67,69,70,70,0,70,65,67,69,69,0,67,67,67,64,60,64,67,65,65,67,69,70,70,0,65,67,69,69,0,60,65,69,67,67,0,67,67,65,67,69,69,0,65,65,67,69,70,70,0,70,70,65,67,69,69,0,67,67,68,64,60,64,67,65)
YL = length(ThisLand)
# Twinkle Twinkle Little Star (in C Major)
TT = c(60,60,67,67,69,69,67,65,65,64,64,62,62,60,67,67,65,65,64,64,62,67,67,65,65,64,64,62,60,60,67,67,69,69,67,65,65,64,64,62,62,60)
TL = length(TT)
# J.B Lully Marche des Trompettes (in C Major)
Lully1 = c(67,72,72,74,76,77,79,76,74,72,67,72,72,74,76,74,76,77,74,67,79,77,76,74,76,77,76,74,72,74,79,74,79,77,76,74,76,77,76,74,72,74,76,74,72,72,0,79,79,79,79,79,72,72,74,76,77,79,76,74,72,67,72,72,74,76,74,76,77,74,76,77,79,79,77,76,74,76,77,76,74,72,74,79,74,79,77,76,74,76,77,76,74,72,74,76,72,72)
L1 = length(Lully1)
#____________________________________________________________________________________________________________
# Waltz in A minor B.150 by F. Chopin (first phrase)
Chop1Notes = c(64,69,71,72,72,74,76,77,71,72,74,81,79,77,76,77,76,75,76,
69,71,72,72,74,76,77,71,72,74,81,79,71,72,0,
64,69,71,72,72,74,76,77,71,72,74,81,79,77,76,77,76,75,76,
72,74,76,76,77,79,81,79,78,79,86,77,76)
Chop1L = length(Chop1Notes)
# No 4. Prelude in E minor Op. 28 by F. Chopin
# Note this piece wanders extensively away from E minor
Chop2Notes = c(59,71,71,72,71,72,71,72,71,70,69,71,69,
71,69,71,69,69,68,69,71,74,72,64,69,66,
69,66,71,69,67,66,60,59,61,66,74,72,71,
71,72,71,72,71,72,71,70,70,79,77,76,
76,75,84,74,74,75,79,71,74,72,76,64,69,66,
69,66,71,69,66,64,64,66,64,66,64,0,64,63,64)
Chop2L = length(Chop2Notes)
# Tocatta in D minor (Bach? BWV 565)
# It is not clear if Bach actually composed this
Bach5Notes = c(81,79,81,0,79,77,76,74,73,74,0,
69,67,69,0,64,65,61,62,
58,61,64,63,0,
61,62,64,61,62,64,61,62,64,61,62,64,65,67,64,
65,67,64,65,67,69,70,67,69,70,67,69,70,67,69,0,
73,74,76,73,74,76,73,74,76,73,74,76,77,79,76,
77,79,76,77,79,81,82,79,81,82,79,81,82,79,81,0,
81,79,82,76,79,82,76,77,81,74,77,81,74,76,79,72,
76,79,72,74,77,70,74,77,70,72,76,69,72,76,69,70,74,67,
70,74,67,69,72,65,69,72,65,67,70,64,67,70,64,
65,69,62,65,69,62,64,67,61,64,67,61,0,70,
69,67,65,64,62,61,59,61,57,61,64,67,65,64,65,0)
Bach5L = length(Bach5Notes)
```
# Fit Test Data to MC
```{r}
Matrix_ATB = markovchainFit(data = ATBNotes, method = "mle")
Matrix_ATB = FillMatrix(Matrix_ATB$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_ATB = Matrix_ATB[-2:-MinNote,-2:-MinNote]
Matrix_ATB = Normalize(Matrix_ATB)
dim(Matrix_ATB)
rowSums(Matrix_ATB)
Matrix_HB = markovchainFit(data = HBNotesG, method = "mle")
Matrix_HB = FillMatrix(Matrix_HB$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_HB = Matrix_HB[-2:-MinNote,-2:-MinNote]
Matrix_HB = Normalize(Matrix_HB)
dim(Matrix_HB)
rowSums(Matrix_HB)
Matrix_YD = markovchainFit(data = YDNotesG, method = "mle")
Matrix_YD = FillMatrix(Matrix_YD$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_YD = Matrix_YD[-2:-MinNote,-2:-MinNote]
Matrix_YD = Normalize(Matrix_YD)
dim(Matrix_YD)
rowSums(Matrix_YD)
Matrix_TL = markovchainFit(data = ThisLand, method = "mle")
Matrix_TL = FillMatrix(Matrix_TL$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_TL = Matrix_TL[-2:-MinNote,-2:-MinNote]
Matrix_TL = Normalize(Matrix_TL)
dim(Matrix_TL)
rowSums(Matrix_TL)
Matrix_TT = markovchainFit(data = TT, method = "mle")
Matrix_TT = FillMatrix(Matrix_TT$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_TT = Matrix_TT[-2:-MinNote,-2:-MinNote]
Matrix_TT = Normalize(Matrix_TT)
dim(Matrix_TT)
rowSums(Matrix_TT)
Matrix_L1 = markovchainFit(data = Lully1, method = "mle")
Matrix_L1 = FillMatrix(Matrix_L1$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_L1 = Matrix_L1[-2:-MinNote,-2:-MinNote]
Matrix_L1 = Normalize(Matrix_L1)
dim(Matrix_L1)
rowSums(Matrix_L1)
Matrix_Chopin1 = markovchainFit(data = Chop1Notes, method = "mle")
Matrix_Chopin1 = FillMatrix(Matrix_Chopin1$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_Chopin1 = Matrix_Chopin1[-2:-MinNote,-2:-MinNote]
Matrix_Chopin1 = Normalize(Matrix_Chopin1)
dim(Matrix_Chopin1)
rowSums(Matrix_Chopin1)
Matrix_Chopin2 = markovchainFit(data = Chop2Notes, method = "mle")
Matrix_Chopin2 = FillMatrix(Matrix_Chopin2$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_Chopin2 = Matrix_Chopin2[-2:-MinNote,-2:-MinNote]
Matrix_Chopin2 = Normalize(Matrix_Chopin2)
dim(Matrix_Chopin2)
rowSums(Matrix_Chopin2)
Matrix_Bach5 = markovchainFit(data = Bach5Notes, method = "mle")
Matrix_Bach5 = FillMatrix(Matrix_Bach5$estimate@transitionMatrix,MaxNote) #MaxNote defined Above
Matrix_Bach5 = Matrix_Bach5[-2:-MinNote,-2:-MinNote]
Matrix_Bach5 = Normalize(Matrix_Bach5)
dim(Matrix_Bach5)
rowSums(Matrix_Bach5)
```
# Test with First Order Markov Chain
```{r}
Markov1 = function(G.Major,G.Minor,TestMC,zfactor,Songname){
G.Major.adj = G.Major + zfactor
# We add in z factor to avoid division by zero in statistic below
# z factor should be a small fraction
G.Major.adj = Normalize(G.Major.adj)
G.Minor.adj = G.Minor + zfactor
G.Minor.adj = Normalize(G.Minor.adj)
TestMC.adj = TestMC + zfactor
TestMC.adj = Normalize(TestMC.adj)
vxG = sum(((TestMC - G.Major.adj)^2/(G.Major.adj)))
Major = c()
K = G.Major.adj
for (k in seq(1,11)) {
#print(k)
## Adjust Master Key up one half step to compare to test song
## Need to pre and post multiply by Shift matrix to move up one-half step
K = ShiftUp %*% K %*% t(ShiftUp)
## Evaluate fit and add to vector of fits
vx = sum(((TestMC.adj - K)^2/(K)))
Major = c(Major,vx)
}
Major = c(Major,vxG)
keys = c('Ab', 'A', 'Bb', 'B', 'C', 'Db', 'D', 'Eb','E', 'F', 'F#','G' )
#____________________________________________________
# Minor Key First Order Statistics
# Calculate G Minor Test Stat
Minor= c()
vxG = sum(((TestMC.adj - G.Minor.adj)^2/(G.Minor.adj)))
K = G.Minor.adj
for (k in seq(1,11)) {
#print(k)
## Adjust Master Key up one half step to compare to test song
## Need to pre and post multiply by Shift matrix to move up one-half step
K = ShiftUp %*% K %*% t(ShiftUp)
## Evaluate fit and add to vector of fits
vx = sum(((TestMC.adj - K)^2/(K)))
Minor = c(Minor,vx)
}
Minor = c(Minor,vxG)
Minor = -1*Minor
MajorData = data.frame(keys,Major)
MinorData = data.frame(keys,Minor)
Data = data.frame(keys,Major,Minor)
#print(Data)
#Data = Data[order(Data$keys), ]
b1 = which(Data$Major== min(Data$Major))
b2 = which(Data$Minor == max(Data$Minor))
colors1 = c(rep("red",times = b1-1),"green",rep("red",times = length(keys)-b1))
colors2 = c(rep("blue",times = b2-1),"green",rep("blue",times = length(keys)-b2))
print(ggplot(Data) + geom_bar(aes(x=keys,y=Major),fill=colors1,stat="identity",position="dodge") + geom_bar(aes(x=keys,y=Minor),fill=colors2,stat="identity",position="dodge")+xlab("Key")+ylab("Test Statistics")+ggtitle("1st Order Test Statistics: ",Songname))
}
```
```{r}
# Major Test Pieces
Markov1(G.Major,G.Minor,Matrix_ATB,1/76,"America the Beautiful")
Markov1(G.Major,G.Minor,Matrix_HB,1/76,"Happy Birthday")
Markov1(G.Major,G.Minor,Matrix_YD,1/76,"Yankee Doodle")
Markov1(G.Major,G.Minor,Matrix_TL,1/76,"This Land is Your Land")
Markov1(G.Major,G.Minor,Matrix_TT,1/76,"Twinkle Twinkle Litte Star")
Markov1(G.Major,G.Minor,Matrix_L1,1/76,"Marches des Trompettes")
# Minor Test Pieces
Markov1(G.Major,G.Minor,Matrix_Chopin1,1/76,"Chopin Waltz in A minor")
Markov1(G.Major,G.Minor,Matrix_Chopin2,1/76,"Chopin Prelude in E minor")
Markov1(G.Major,G.Minor,Matrix_Bach5,1/76,"?Bach Tocatta in D minor BWV 565")
```
Prediction Results from TEST DATA:
Correct Major Key Predictions: America the Beautiful, Happy Birthday, Twinkle Twinkle, Marches des Trompettes
Incorrect Major Key Predictions: Yankee Doodle, This Land is Your Land,
Correct Minor Key Predictions: Chopin Waltz in A minor
Incorrect Minor Key Predictions: Chopin Prelude in E Minor, Tocatta in D minor