commit 6753c417ec21c5dc841ec36a2a5aac0997cc1ead Author: Mark Hoekveen Date: Fri May 19 09:56:13 2023 +0200 initial commit diff --git a/run.py b/run.py new file mode 100644 index 0000000..d7729bd --- /dev/null +++ b/run.py @@ -0,0 +1,110 @@ +from __future__ import print_function + +import logging +import sys +import time +from random import randrange +import subprocess + +import tkinter as tk +from PIL import Image, ImageTk + +from rtmidi.midiutil import open_midiinput + +log = logging.getLogger('midiin_callback') +logging.basicConfig(level=logging.INFO) + +notes_sharp = ["c", "cis", "d", "dis", "e", "f", "fis", "g", "gis", "a", "ais", "b"] + +lilypond = ''' +\paper { + #(set-paper-size "a10landscape") + indent = 0\mm + line-width = 110\mm + oddHeaderMarkup = "" + evenHeaderMarkup = "" + oddFooterMarkup = "" + evenFooterMarkup = "" +} + +''' + +window = tk.Tk() + +class Trainer(): + def __init__(self): + self.secret = 0 + self.lb = 60 + self.ub = 84 # 108 + self.image = None + self.image_label = tk.Label(window) + self.image_label.pack() + self.newNote() + + # Gets a new random note, outputs it to file + def newNote(self): + self.secret = randrange(self.lb, self.ub) + self.print() + ly = lilypond + f"{{{self.convertNote(self.secret)}}}" + with open("lily.txt", "w") as f: + f.write(ly) + f.close() + wait_for = subprocess.Popen(["lilypond", "-dpreview", "-dbackend=eps", "-dresolution=600", "--png", "lily.txt"]) + self.refreshImage(wait_for) + + def refreshImage(self, wait_for=None): + if wait_for: + wait_for.wait() + if self.image: + self.image.close() + self.image = Image.open("lily.png") + photo = ImageTk.PhotoImage(self.image) + self.image_label.configure(image=photo) + self.image_label.image = photo + + + def guess(self, note): + guess = (note == self.secret) + if guess: + self.newNote() + return guess + + # Convert midi pitch to lilypond notation + def convertNote(self, pitch): + octave = int(pitch / 12) - 4 + oct_str = -octave*"," if octave < 0 else octave*"'" + note = notes_sharp[(pitch % 12)] + return f"{note}{oct_str}" + + def print(self): + print(f"Current midi note: {self.secret}") + print(self.convertNote(self.secret)) + + +t = Trainer() + +class MidiInputHandler(object): + def __init__(self, port): + self.port = port + + def __call__(self, event, data=None): + message, deltatime = event + (ev, note, vel) = message + if ev == 144: # note on + print(f"Pressed note {note}") + print(t.convertNote(note)) + t.guess(note) + +# Prompts user for MIDI input port, unless a valid port number or name given +port = sys.argv[1] if len(sys.argv) > 1 else None + +try: + midiin, port_name = open_midiinput(port) +except (EOFError, KeyboardInterrupt): + sys.exit() + +midiin.set_callback(MidiInputHandler(port_name)) + +window.mainloop() +midiin.close_port() +del midiin