Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # from _overlapped import NULL
- import math, mido, numpy, scipy
- from mido import MidiFile
- import music21
- import time
- import operator
- import pylab as plt
- from matplotlib_venn import venn3
- input_files = {
- "in/Star Trek TNG kurz.mid": "F minor", "in/sleepsat.mid": "E- major", "in/silentnight.mid": "C major",
- "in/shephard.mid": "F major", "in/sesame.mid": "C minor",
- "in/scooby.mid": "C major", "in/Sara.mid": "C major", "in/santacom.mid": "C major", "in/rudolph.mid": "C major",
- "in/Rikasmies.mid": "C minor",
- "in/reichwaehr.mid": "C minor", "in/prima.mid": "C major", "in/policeacademy.mid": "C major",
- "in/pipi-langstrumpf.mid": "C major", "in/Petteri.mid": "C major",
- "in/superman.mid": "G major", "in/StheB.mid": "G major", "in/Sternenhimmel.mid": "G major",
- "in/starwars-imperial.mid": "D minor", "in/starwars.mid": "C minor",
- "in/99 Luftballons.mid": "D minor", "in/90210.mid": "F major", "in/Zorbas.mid": "D major",
- "in/ZieGindsKomtDeStoomboot.mid": "F major",
- "in/you R not alone.mid": "D minor",
- "in/X Files.mid": "E minor", "in/winnerabba.mid": "B major", "in/WalkOfLife.mid": "A major",
- "in/Uralinpihlaja.mid": "D minor", "in/tlc.mid": "C major",
- "in/Titanic.mid": "C major", "in/tannebaum.mid": "F major",
- "in/oxygen.mid": "C minor", "in/ohcome.mid": "D minor", "in/Oh_come.mid": "G major",
- "in/offspring_getajob.mid": "A minor", "in/o_little.mid": "F major",
- "in/o_la_paloma.mid": "G major", "in/nur getrumt.mid": "C major",
- "in/Niemals in New York 2.mid": "C major", "in/nie wieder.mid": "C major", "in/murka.mid": "D minor",
- "in/Mit 66 Jahren.mid": "F major", "in/Mission_impossible.mid": "E- major",
- "in/mief.mid": "C major", "in/marmor-stein.mid": "C major",
- "in/major tom.mid": "F major", "in/Macarena.mid": "F major",
- "in/LivingRoom.mid": "D minor", "in/liquido.mid": "A minor",
- "in/Lindenstrae2.mid": "C major", "in/kiss.mid": "A minor", "in/Insel m. 2 Bergen.mid": "C major",
- "in/indiana.mid": "C major", "in/howmuchisthefish.mid": "A minor", "in/HoheBerge.mid": "D major",
- "in/GWein.mid": "A minor",
- "in/GuteZeiten.mid": "A minor", "in/Griechischer Wein2.mid": "A minor",
- "in/goodbad.mid": "A minor", "in/good.mid": "F major", "in/godfather.mid": "C minor",
- "in/god_rest.mid": "D minor", "in/gl_ck.mid": "C major", "in/FofS.mid": "G major",
- "in/flintstones.mid": "A minor", "in/flieger.mid": "C major",
- "in/Eldanka.mid": "D minor", "in/Elamaa_juoksuhaudoissa.mid": "G minor",
- "in/einfallfuer2.mid": "A minor", "in/Ein_Fall_Fuer_Zwei.mid": "A minor",
- "in/east_end.mid": "B- major", "in/DschingesKhan.mid": "A minor",
- "in/deutschlandlied.mid": "G major", "in/denneboom.mid": "F major",
- # "in/davy.mid": "C major",
- "in/Cucaracha.mid": "C major",
- "in/cccp.mid": "A major", "in/boom.mid": "F major", "in/Bittersweetharmonie.mid": "A- major",
- "in/big big girl.mid": "C major", "in/Biene Maja.mid": "C major",
- "in/away.mid": "F major", "in/advkal8.mid": "C major", "in/advkal10.mid": "C major",
- "in/advkal12.mid": "A minor", "in/advkal15.mid": "C major",
- "in/advkal17.mid": "C major"
- }
- major_profile = [6.35, 2.23, 3.48, 2.33, 4.38, 4.09, 2.52, 5.19, 2.39, 3.66, 2.29, 2.88]
- minor_profile = [5.38, 2.60, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17, 6.33, 2.68, 3.52]
- ignored_messages = ["note_off", "polytouch", "control_change", "program_change", "aftertouch",
- "pitchwheel", "sysex", "quarter_frame", "songpos", "song_select", "tune_request",
- "clock", "start", "continue", "stop", "active_sensing", "reset"]
- correlate_krumh = {"10": "A", "11": "B-", "12": "B", "1": "C", "2": "D-", "3": "D", "4": "E-",
- "5": "E", "6": "F", "7": "G-", "8": "G", "9": "A-"}
- correlate_algo = {9: "A", 10: "A ♯ or B ♭", 11: "B", 0: "C", 1: "C ♯ or D ♭", 2: "D", 3: "D ♯ or E ♭",
- 4: "E", 5: "F", 6: "F ♯ or G ♭", 7: "G", 8: "G ♯ or A ♭"}
- def get_key(midi_file):
- r_major = [0] * 12
- r_minor = [0] * 12
- frequency = [0] * 12
- y = [0] * 12
- for i in midi_file.tracks:
- for j in i[2:]:
- # print("This is j: ", j)
- if not j.is_meta and not ignored_messages.__contains__(j.type): # and j.velocity != 0 :
- # print("This is j: ", j)
- my_note = j.note
- frequency[my_note % 12] += 1
- x = major_profile
- for i in range(12):
- for j in range(12):
- y[j] = frequency[(j + i) % 12]
- help = helper(x, y)
- r_major[i] = help[0] / help[1]
- x = minor_profile
- for i in range(12):
- for j in range(12):
- y[j] = frequency[(j + i + 3) % 12]
- help = helper(x, y)
- r_minor[i] = help[0] / help[1]
- max_r = -100000
- fit_key = 0
- for i in range(12):
- if max_r < r_major[i]:
- max_r = r_major[i]
- fit_key = i + 1
- lad = "major"
- for i in range(12):
- if max_r < r_minor[i]:
- max_r = r_minor[i]
- fit_key = -i - 1
- lad = "minor"
- return (str)(correlate_krumh[(str)(abs(fit_key))] + " " + (str)(lad))
- def helper(x, y):
- meanX = mean(x)
- meanY = mean(y)
- numerator = 0
- denominator_one = 0
- denominator_two = 0
- for j in range(12):
- numerator += (x[j] - meanX) * (y[j] - meanY)
- denominator_one += (x[j] - meanX) * (x[j] - meanX)
- denominator_two += (y[j] - meanY) * (y[j] - meanY)
- denominator = math.sqrt(denominator_one * denominator_two)
- return numerator, denominator
- def mean(arr):
- size = len(arr)
- summ = 0
- for i in range(size):
- summ += arr[i]
- return summ / size
- notes_letters = [['C', 'A'],
- ['F', 'D', 'G', 'E'],
- ['B-', 'G', 'D', 'B'],
- ['E-', 'C', 'A', 'F+'],
- ['A-', 'F', 'E', 'C+'],
- ['D-', 'B-', 'B', 'G+'],
- ['G-', 'E-', 'F+', 'D+'],
- ['C-', 'A-', 'C+', 'A+']]
- signs_by_key = {
- 'C major': 0, 'A minor': 0,
- 'F major': 1, 'D minor': 1, 'G major': 1, 'E minor': 1,
- 'B- major': 2, 'G minor': 2, 'D major': 2, 'B minor': 2,
- 'E- major': 3, 'C minor': 3, 'A major': 3, 'F+ minor': 3,
- 'A- major': 4, 'F minor': 4, 'E major': 4, 'C+ minor': 4,
- 'D- major': 5, 'B- minor': 5, 'B major': 5, 'G+ minor': 5,
- 'G- major': 6, 'E- minor': 6, 'F+ major': 6, 'D+ minor': 6,
- }
- notes_num = [[0, 9],
- [7, 5, 4, 2],
- [2, 10, 11, 7],
- [9, 3, 6, 0],
- [4, 8, 1, 5],
- [11, 1, 8, 10],
- [6, 6, 3, 3],
- [1, 11, 10, 8]]
- signs = [6, 1, 8, 3, 10]
- sharps = [6, 1, 8, 3, 10, 5, 0]
- flats = [10, 3, 8, 1, 6, 11, 4]
- def is_a_sign(x):
- return signs.__contains__(x)
- def is_a_sharp(x):
- return sharps.__contains__(x)
- def is_a_flat(x):
- return flats.__contains__(x)
- major_intervals = [2, 2, 1, 2, 2, 2, 1]
- minor_intervals = [2, 1, 2, 2, 1, 2, 2]
- relative_key = {"C major": "A minor", "D- major": "B- minor", "D major": "B minor", "E- major": "C minor",
- "E major": "C+ minor", "F major": "A minor", "F+ major": "D+ minor", "G- major": "E- minor",
- "G major": "E minor", "A- major": "F minor", "A major": "F+ minor", "B- major": "G minor",
- "B major": "G+ minor",
- }
- def algo(file):
- frequency = {0: 0, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0, 10: 0, 11: 0}
- note_count = 0
- last_note = 0
- for i in file.tracks:
- # print("track ", i)
- for j in i[2:len(i)]:
- if not j.is_meta and not ignored_messages.__contains__(j.type) and j.velocity != 0:
- # print("msg ", j)
- last_note = j.note
- note_count += 1
- frequency[last_note % 12] += 1
- # print("last_note ", last_note)
- # print("frequency", frequency)
- last_note = last_note % 12
- the_signs = []
- the_sharps = []
- the_flats = []
- sign_count = 0
- meanX = mean(frequency)
- # print("mean freq", meanX)
- flag = False
- we_have_flats = False
- sorted_frequency = sorted(frequency.items(), key=operator.itemgetter(1))
- sorted_frequency.reverse()
- # print("sorted frequency", sorted_frequency)
- sorted_frequency = sorted_frequency[:8]
- # print("most common ", sorted_frequency)
- maybe_a_sign = []
- for i in range(12):
- if frequency[i] > 1:
- # if sign_count >= 5:
- # flag = True
- # if is_a_sharp(i):
- # print(frequency[i], "sign_count >= 5, a sharp")
- # the_sharps.append(i)
- # sign_count += 1
- # sharp_count += 1
- # elif is_a_flat(i):
- # print(frequency[i], "sign_count >= 5, a flat")
- # the_flats.append(i)
- # sign_count += 1
- # flat_count += 1
- if is_a_sign(i):
- the_signs.append(i)
- sign_count += 1
- if the_signs.__contains__(signs[0]):
- we_have_sharps = True
- for x in the_signs: the_sharps.append(x)
- elif the_signs.__contains__(signs[len(signs) - 1]):
- we_have_flats = True
- for x in the_signs: the_flats.append(x)
- elif len(the_signs) == 0:
- pass
- # print("no signs")
- # else:
- # if the_signs.__contains__(signs[1] or
- # the_signs.__contains__(signs[len(signs) - 2])):
- # print('how can it be')
- # print("hz")
- # print("note_count ", note_count)
- # print("the signs ", the_signs, "signs count ", sign_count)
- # print("the sharps ", the_sharps, "\nthe_flats ", the_flats)
- potential_note_num = []
- for i in range(7):
- for j in range(0, 1):
- if sorted_frequency[i][1] != 0:
- potential_note_num.append(sorted_frequency[i][j])
- potential_notes_letters = []
- for i in range(len(potential_note_num)):
- # print("potential note num ",correlate[potential_note_num[i]])
- potential_notes_letters.append(correlate_algo[(potential_note_num[i])])
- # print("potential notes ", potential_note_num)
- k = 0
- for n in potential_notes_letters:
- if len(n) > 2:
- if we_have_flats:
- potential_notes_letters[k] = n[7:]
- else:
- potential_notes_letters[k] = n[:3]
- k += 1
- # print("potential notes ", potential_notes_letters)
- # print("num of signs is ", sign_count, "so it should be one of these", notes_letters[sign_count],
- # "we have flats? ",
- # we_have_flats, ", so it is ", notes_letters[sign_count][:2])
- # print("let's try to determine if it is major or minor")
- if sign_count == 0 or we_have_flats:
- major_begin = notes_num[sign_count][0]
- minor_begin = notes_num[sign_count][1]
- else:
- major_begin = notes_num[sign_count][2]
- minor_begin = notes_num[sign_count][3]
- potential_note_num.sort()
- major = []
- minor = []
- for i in major_intervals:
- major_begin += i
- major.append(major_begin % 12)
- for i in minor_intervals:
- minor_begin += i
- minor.append(minor_begin % 12)
- # print(potential_note_num)
- major_count = 0
- minor_count = 0
- for i in range(7):
- if potential_note_num.__contains__(i) and major.__contains__(i):
- major_count += 1
- if potential_note_num.__contains__(i) and minor.__contains__(i):
- minor_count += 1
- if major_count >= minor_count and major_count >= 2:
- if sign_count == 0 or we_have_flats:
- # print('major no signs last note ', last_note, notes_letters[sign_count][0])
- if (correlate_algo[(last_note)]) == str(notes_letters[sign_count][0]):
- flag = True
- return str(notes_letters[sign_count][0]) + " major"
- else:
- # print('major sharps last note ', last_note, notes_letters[sign_count][2])
- if (correlate_algo[(last_note)]) == str(notes_letters[sign_count][2]):
- flag = True
- return str(notes_letters[sign_count][2]) + " major"
- elif minor_count >= major_count and minor_count >= 2:
- if sign_count == 0 or we_have_flats:
- # print('minor no signs last note ', last_note, notes_letters[sign_count][1])
- if (correlate_algo[(last_note)]) == str(notes_letters[sign_count][1]):
- flag = True
- return str(notes_letters[sign_count][1]) + " minor"
- else:
- # print('minor sharps last note ', last_note, notes_letters[sign_count][3])
- if str(correlate_algo[(last_note)]) == str(notes_letters[sign_count][3]):
- flag = True
- return str(notes_letters[sign_count][3]) + " minor"
- # else:
- # print("maybe do smth else?")
- def is_paral(one, two):
- return relative_key.get(str(one)) == str(two) or relative_key.get(str(two)) == str(one)
- def is_true(key):
- return input_files[x] == key
- # return list(mydict_num.keys())[list(mydict_num.values()).index([0, 9])] == notes_num[input_files[x]]
- # " m21 par or true", "krumhansl par or true", " "," ",
- print("true key ", "music21 ", "Krumhansl ", " algo2 ",
- "music21 = krum ", "", "music21 == algo", " ", " krum = algo ", )
- music21_true = False
- krumhansl_true = False
- algo_true = False
- music21_krumhansl = False
- music21_algo = False
- krumhansl_algo = False
- all_say_the_same = False
- all_say_the_same_and_true = False
- at_least_one_true = False
- music21_relative = False
- krumhansl_relative = False
- num_of_files = len(input_files)
- music21_num = 0
- krumhansl_num = 0
- music21_krumhansl_num = 0
- music21_parallel_number = 0
- krumhansl_parallel_number = 0
- krum_algo_num = 0
- algo_num = 0
- music21_algo_num = 0
- intersection = 0
- at_least_one_num = 0
- i = 0
- for x in input_files:
- key = music21.converter.parse(x).analyze('key')
- mid = MidiFile(x)
- krum_key = get_key(mid)
- algo_key = algo(mid)
- if is_true(str(key.tonic.name + " " + key.mode)):
- music21_true = True
- music21_num += 1
- if input_files[x] == krum_key:
- krumhansl_true = True
- krumhansl_num += 1
- if input_files[x] == str(algo_key):
- algo_true = True
- algo_num += 1
- if is_true(str(krum_key)) and is_true(str(key.tonic.name + " " + key.mode)) and is_true(str(algo_key)):
- # print("all the same! ")
- intersection += 1
- if is_true(str(krum_key)) or is_true(str(key.tonic.name + " " + key.mode)) or is_true(str(algo_key)):
- # print("all the same! ")
- at_least_one_num += 1
- if is_true(str(krum_key)) and is_true(str(key.tonic.name + " " + key.mode)):
- music21_krumhansl = True
- music21_krumhansl_num += 1
- if is_true(str(algo_key)) and is_true(str(key.tonic.name + " " + key.mode)):
- music21_algo = True
- music21_algo_num += 1
- if is_true(str(krum_key)) and is_true(str(algo_key)):
- krumhansl_algo = True
- krum_algo_num += 1
- if str(key.tonic.name + " " + key.mode) == str(relative_key.get(input_files[x])) or music21_true \
- or (str)(input_files[x]) == (str)(relative_key.get(key.tonic.name + " " + key.mode)):
- music21_relative = True
- music21_parallel_number += 1
- if str(krum_key) == (str)(relative_key.get(input_files[x])) or krumhansl_true \
- or (str)(input_files[x]) == (str)(relative_key.get(krum_key)):
- krumhansl_relative = True
- krumhansl_parallel_number += 1
- # music21_relative, krumhansl_relative, " ",
- print(i, input_files[x], " ", key.tonic.name, key.mode, " ", krum_key, " ", algo_key,
- " ", music21_krumhansl, " ", music21_algo, " ", krumhansl_algo)
- i += 1
- music21_true = False
- krumhansl_true = False
- algo_true = False
- music21_krumhansl = False
- music21_algo = False
- krumhansl_algo = False
- all_say_the_same = False
- all_say_the_same_and_true = False
- at_least_one_true = False
- music21_relative = False
- krumhansl_relative = False
- # music21_parallel_number * 100 // num_of_files, krumhansl_parallel_number * 100 // num_of_files,
- print("Percent ", " ", (format(music21_num * 100 / num_of_files,".2f")), " ",
- (format(krumhansl_num * 100 / num_of_files, ".2f")), " ",
- (format(algo_num * 100 / num_of_files, ".2f")), " ",
- (format(music21_krumhansl_num * 100 / num_of_files, ".2f")), " ",
- # algo_num * 100 / num_of_files," ",
- (format(music21_algo_num * 100 / num_of_files, ".2f")), " ",
- (format(krum_algo_num * 100 / num_of_files, ".2f")))
- print("num of files considered: ", len(input_files))
- print(intersection, at_least_one_num)
- print(music21_num, krumhansl_num, algo_num)
- print(music21_krumhansl_num, music21_algo_num, krum_algo_num)
- my_subsets = [0] * 7
- my_subsets[6] = intersection #* 100 // at_least_one_num
- # my_subsets[6] = all_number * 100 / at_least_one_num
- my_subsets[2] = music21_krumhansl_num - my_subsets[6]
- my_subsets[4] = music21_algo_num - my_subsets[6]
- # print(music21_num, my_subsets[6], my_subsets[2], my_subsets[4])
- my_subsets[0] = music21_num - my_subsets[2] - my_subsets[4] - my_subsets[6]
- my_subsets[5] = krum_algo_num - my_subsets[6]
- my_subsets[1] = krumhansl_num - my_subsets[2] - my_subsets[5] - my_subsets[6]
- my_subsets[3] = algo_num - my_subsets[4] - my_subsets[5] - my_subsets[6]
- print(my_subsets)
- for i in range(7):
- if my_subsets[i] < 0:
- my_subsets[i] = 0
- for i in range(7):
- my_subsets[i] = (my_subsets[i] * 100 / at_least_one_num)
- # my_subsets[i] = format(my_subsets[i],".2f")
- my_subsets[i] = round(my_subsets[i], 2)
- venn3(subsets=my_subsets, set_labels=('music21', 'Krumhansl', 'algorithm SA'))
- plt.title("Percent of intersection of right answers between algorithms")
- plt.show()
- k = 0
- n = 0
- i = 0
- for x in input_files:
- algo_key = algo(MidiFile(x))
- # print(input_files[x], algo_key, (is_paral(input_files[x], algo_key) or is_true(algo_key)))
- # # print(signs_by_key[str(input_files[x])])
- # # print(signs_by_key[input_files[i][1]], signs_by_key[algo_key])
- if is_paral(input_files[x], algo_key) or is_true(algo_key):
- k += 1
- if is_true(algo_key):
- n += 1
- i += 1
- # print(k / len(input_files), n / len(input_files))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement