Skip to content

Instantly share code, notes, and snippets.

@an0ndev
Created May 6, 2024 00:57
Show Gist options
  • Select an option

  • Save an0ndev/b06426f7cc597fbe265b4581eb891c68 to your computer and use it in GitHub Desktop.

Select an option

Save an0ndev/b06426f7cc597fbe265b4581eb891c68 to your computer and use it in GitHub Desktop.
Set theory analysis tool for sheet music
import tkinter
import math
import functools
window = tkinter.Tk()
keys = ["c", "c#", "d", "d#", "e", "f", "f#", "g", "g#", "a", "a#", "b"]
text_radius = 100
text_size = 16
font = ("Arial", text_size, "normal")
window_dimension = int((text_radius * 2.5) + (text_size * 3))
base_pos = (window_dimension // 2, window_dimension // 2)
buttons = {}
def handle_clock_input(piano_key: str, update: bool):
button, is_clicked = buttons[piano_key]
new_is_clicked = not is_clicked
button.configure(background="red" if new_is_clicked else "white")
buttons[piano_key] = (button, new_is_clicked)
if update:
recalculate_intervals()
def recalculate_intervals():
pressed_buttons = list(filter(lambda button_name: buttons[button_name][1], buttons.keys()))
if len(pressed_buttons) < 2:
window.title("no interval")
return
all_keys_and_intervals = []
for start_pos in range(len(pressed_buttons)):
forward_keys = pressed_buttons[start_pos:] + pressed_buttons[:start_pos]
forward_intervals = []
for idx, k in enumerate(forward_keys):
if idx == 0:
continue
last = forward_keys[idx - 1]
last_num = keys.index(last)
k_num = keys.index(k)
while k_num < last_num:
k_num += len(keys)
interval = k_num - last_num
forward_intervals.append(interval)
all_keys_and_intervals.append((forward_keys, forward_intervals))
backward_keys = list(reversed(pressed_buttons[:(start_pos + 1)])) + list(reversed(pressed_buttons[(start_pos + 1):]))
backward_intervals = []
for idx, k in enumerate(backward_keys):
if idx == 0:
continue
last = backward_keys[idx - 1]
last_num = keys.index(last)
k_num = keys.index(k)
while k_num > last_num:
k_num -= len(keys)
interval = last_num - k_num
backward_intervals.append(interval)
all_keys_and_intervals.append((backward_keys, backward_intervals))
print(f"forward from {start_pos}: {forward_keys} ({forward_intervals})")
print(f"backward from {start_pos}: {backward_keys} ({backward_intervals})")
print(all_keys_and_intervals)
min_keys = all_keys_and_intervals[0][0]
min_intervals = all_keys_and_intervals[0][1]
min_total = sum(all_keys_and_intervals[0][1])
min_first = all_keys_and_intervals[0][1][0]
for this_keys, intervals in all_keys_and_intervals[1:]:
if sum(intervals) > min_total:
continue
if sum(intervals) < min_total:
min_keys = this_keys
min_intervals = intervals
min_total = sum(intervals)
min_first = intervals[0]
continue
if intervals[0] < min_first:
min_keys = this_keys
min_intervals = intervals
min_total = sum(intervals)
min_first = intervals[0]
print(min_keys, min_intervals, min_first, min_total)
min_set = [0]
for interval in min_intervals:
min_set.append(min_set[-1] + interval)
window.title(" ".join(map(str, min_set)))
for key, pos in zip(keys, map(lambda _: (math.pi / 2) - _ * (math.pi * 2 / len(keys)), range(len(keys)))):
x = base_pos[0] + (math.cos(pos) * text_radius)
y = base_pos[1] - (math.sin(pos) * text_radius)
item = tkinter.Button(window, text=key, font=font, command=functools.partial(handle_clock_input, key, True))
item.place(x=x, y=y, anchor="center")
buttons[key] = (item, False)
def clear():
pressed_buttons = list(filter(lambda button_name: buttons[button_name][1], buttons.keys()))
for idx, button in enumerate(pressed_buttons):
handle_clock_input(button, idx == len(pressed_buttons) - 1)
clear_btn = tkinter.Button(window, text="clear", font=font, command=clear)
clear_btn.place(x=base_pos[0], y=base_pos[1], anchor="center")
window.geometry(f"{window_dimension}x{window_dimension}")
recalculate_intervals()
window.mainloop()
@an0ndev
Copy link
Author

an0ndev commented May 6, 2024

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment