initial commit
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user