-
Notifications
You must be signed in to change notification settings - Fork 1
/
NoteCountExtendedMultiProc.py
174 lines (140 loc) · 7.62 KB
/
NoteCountExtendedMultiProc.py
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
import os
import math
import mido
from multiprocessing import Pool
# Returns a list of times in format [H, M, S] given a time in seconds
def returnTime(time):
hoursWithRemainder = time/3600
minutesWithRemainder = 60*(hoursWithRemainder - math.floor(hoursWithRemainder))
hours = math.floor(hoursWithRemainder)
minutes = math.floor(minutesWithRemainder)
seconds = round(60*(minutesWithRemainder - math.floor(minutesWithRemainder))) # Round to remove float issues
return [hours, minutes, seconds]
# Takes a midi file as an input, and returns a list of keys pressed
def parseMidiFile(mid):
keyList = initializeList()
for msg in mid:
if msg.type == "note_on":
keyListIndex = msg.note
# Conversion between midi value and note:
# MIDI = note + 20
# BUT, the list is "0-indexed", meaning that
# A0 is note 1 but index 0 in the list!
keyListIndex -= 21
keyList[keyListIndex][1] += 1
return keyList
def initializeList():
keyList = list()
keys = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
octaves = ["0", "1", "2", "3", "4", "5", "6", "7"] # Notes from A0->C8, strategy here is to create a list with
# C0->B8, then remove C0->G#0, and then add C8
for octave in octaves:
for key in keys:
keyList.append([key + octave, 0]) # signature
for i in range(9): #Remove the first element 9 times in a row, eg, C0->G#0
keyList.pop(0)
keyList.append(["C8", 0])
return keyList
# Adds all of the keypresses from tmpKeyList to keyList
def addKeyLists(keyList, tmpKeyList):
for i in range(len(keyList)):
keyList[i][1] = keyList[i][1] + tmpKeyList[i][1]
return keyList
# Prints the final key list
def printKeyList(keyList):
print("Breakdown of how many times each key was played: ")
for i in range(10*12):
print("-", end="")
print()
print("| {:>8} | {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}|".\
format("Octave","0", "1", "2", "3", "4", "5", "6", "7", "8"))
for i in range(10*12):
print("-", end="")
print()
keys = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
for i in range(12):
#Handle special cases separetly (A0->B0 and C8 causes issues)
if i == 0:
print("|{:>9} | {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}|".format(keys[i],\
"---", str(keyList[i+3][1]), str(keyList[i + 3 + 12][1]), str(keyList[i + 3 + 24][1]),\
str(keyList[i + 3 + 36][1]), str(keyList[i + 3 + 48][1]), str(keyList[i + 3 + 60][1]),\
str(keyList[i + 3 + 72][1]), str(keyList[i + 3 + 84][1])))
elif i >= 9:
print("|{:>9} | {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}|".format(keys[i],\
str(keyList[i-9][1]), str(keyList[i+3][1]), str(keyList[i + 3 + 12][1]), str(keyList[i + 3 + 24][1]),\
str(keyList[i + 3 + 36][1]), str(keyList[i + 3 + 48][1]), str(keyList[i + 3 + 60][1]),\
str(keyList[i + 3 + 72][1]), "---"))
else:
print("|{:>9} | {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}| {:<10}|".format(keys[i],\
"---", str(keyList[i+3][1]), str(keyList[i + 3 + 12][1]), str(keyList[i + 3 + 24][1]),\
str(keyList[i + 3 + 36][1]), str(keyList[i + 3 + 48][1]), str(keyList[i + 3 + 60][1]),\
str(keyList[i + 3 + 72][1]), "---"))
for i in range(10*12):
print("-", end="")
print()
# Print least used key and most used key:
indexLeastUsed = 0
indexMostUsed = 0
for i in range(len(keyList)):
if keyList[i][1] < keyList[indexLeastUsed][1]:
indexLeastUsed = i
if keyList[i][1] > keyList[indexMostUsed][1]:
indexMostUsed = i
print("Least used key: " + keyList[indexLeastUsed][0] + " with " + str(keyList[indexLeastUsed][1]) + " presses")
print("Most used key: " + keyList[indexMostUsed][0] + " with " + str(keyList[indexMostUsed][1]) + " presses")
def calcKeyList(file):
keyList = initializeList()
try:
keyList = parseMidiFile(mido.MidiFile(file[0] + "/" + file[1] + "/" + file[2]))
except:
try:
keyList = parseMidiFile(mido.MidiFile(file[0] + "\\" + file[1] + "\\" + file[2]))
except OSError:
print("Warning: File '" + file[0] + "/" + file[1] + "/" + file[2] + "' is likely corrupted!"\
+ " The file has been excluded from the per note breakdown but is still included in total.")
return keyList
def main():
yearList = os.listdir() # List of all years that exist in the MIDI archive
monthList = os.listdir() # List of all months that exist, created on a "per archive year" basis
sumNotes = 0 # Amount of notes played
sumTime = 0 # Amount of time played
keyList = initializeList() # A list of all midi keys on the keyboard (NOTE: assumes 88 keys),
# and how much they have been played. Signature of item in keyList:
# ["keyname", numpressed], ex: ["C4", 5124] if the key C4 has been
# played 5124 times
corruptFileWarning = False # Midi parser raises error if corrupt file is found, print file name and warning at the end
fileList = list() #List of files for the midi parser to go through
for i in range(len(yearList)):
if "." not in yearList[i]: # Looks for folders, and not items which contain "." (mitigation to ignore this file in search)
monthList[i] = os.listdir(yearList[i])
for j in range(len(monthList[i])):
try: #If the *NIX way of path resolving does not work, try the Windows way
archivelist = os.listdir(yearList[i] + "/" + monthList[i][j])
except:
archivelist = os.listdir(yearList[i] + "\\" + monthList[i][j])
# Calculate the sum of notes and time played
for k in range(len(archivelist)):
row = archivelist[k].split() # The file name split into a list, split by space
# Indices for the row:
# 0 - Date (YYYY-MM-DD)
# 1 - Time (HHMM)
# 2 - Day of the week: (Day), Ex: (Wednesday)
# 3 - How many notes
# 4 - The word "notes,"
# 5 - Duration of the file (in seconds)
# 6 - The word "seconds" followed by file extension (.mid)
sumNotes += int(row[3])
sumTime += float(row[5])
midiTemp = 0 #"Declare variable"
fileList.append([yearList[i], monthList[i][j], archivelist[k]])
#Create a list of keylists for all midi files, and then calculate the sum afterwards, use pooling to run on all cores.
subKeyLists = list()
with Pool() as pool:
subKeyLists = pool.map(calcKeyList, fileList)
for i in range(len(subKeyLists)):
keyList = addKeyLists(keyList, subKeyLists[i])
timePlayedList = returnTime(sumTime)
print("You've played for: " + str(timePlayedList[0]) + " hour(s), " + str(timePlayedList[1])\
+ " minute(s) and " + str(timePlayedList[2]) + " second(s), with " + str(sumNotes) + " notes! Wow!")
printKeyList(keyList)
main()