Improve midi conversion (actually make it work properly)

This commit is contained in:
2025-03-09 21:11:21 +01:00
parent 6fad58dd64
commit 77d621167a

View File

@@ -1,10 +1,11 @@
from mido import MidiFile from mido import MidiFile, tempo2bpm
import math
import pyperclip as pc import pyperclip as pc
class MidiManagement: class MidiManagement:
def __init__(self): def __init__(self):
pass self.note_reference = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B']
def addToClipboard(self, text): def addToClipboard(self, text):
pc.copy(text) pc.copy(text)
@@ -25,75 +26,56 @@ class MidiManagement:
tracknumber += 1 tracknumber += 1
output_list = [] output_list = []
tracked_notes = []
bpm = 0
timing = 20000
# Track messages # Track messages
for msg in mid.tracks[tracknumber]: for msg in mid.tracks[tracknumber]:
midi_msg = str(msg) if msg.type == "note_on":
if midi_msg[0:8] == "note_on ":
try: try:
msg_loc = midi_msg.index('note=') tracked_notes.append(self.get_note_as_micro_bit_string(msg))
note = midi_msg[msg_loc + 5:msg_loc + 7]
note_height = int(note)
note_decod_oct = note_height // 12
note_decode_tone = note_height % 12
note_ext = ""
if note_decode_tone == 1:
note_ext = "C"
elif note_decode_tone == 2:
note_ext = "C#"
elif note_decode_tone == 3:
note_ext = "D"
elif note_decode_tone == 4:
note_ext = "D#"
elif note_decode_tone == 5:
note_ext = "E"
elif note_decode_tone == 6:
note_ext = "F"
elif note_decode_tone == 7:
note_ext = "F#"
elif note_decode_tone == 8:
note_ext = "G"
elif note_decode_tone == 9:
note_ext = "G#"
elif note_decode_tone == 10:
note_ext = "A"
elif note_decode_tone == 11:
note_ext = "A#"
elif note_decode_tone == 12:
note_ext = "H"
ext_shortened = midi_msg[40:]
pos = 0
for buchstabe in ext_shortened:
if buchstabe == "=":
pos += 1
break
else:
pos += 1
timing_exp = ext_shortened[pos:]
output = note_ext
output += str(note_decod_oct)
output += f":{timing_exp}"
output_list.append(str(output))
except: except:
pass pass
elif midi_msg[0:8] == "note_off": elif msg.type == "note_off":
ext_shortened = midi_msg[40:] # End tracked note at time offset for midi msg (that is relative to start)
pos = 0 note = ''
for buchstabe in ext_shortened: try:
if buchstabe == "=": note = self.get_note_as_micro_bit_string(msg)
pos += 1 except:
break pass
else:
pos += 1
output = "R"
output += f":{pos}"
timing_exp = ext_shortened[pos:] # Find note in tracked notes, ignore if not in there
output_list.append(output) index = -1
for n in range(len(tracked_notes)):
if tracked_notes[n] == note:
index = n
break;
# Get duration
if index >= 0:
tracked_notes.remove(note)
t = math.floor(msg.time / timing)
output_list.append(note + ':' + str(t))
else: else:
try:
midi_msg = str(msg)
i = midi_msg.index('tempo=') + 6
units = int(midi_msg[i:i + midi_msg[i:].index(',')])
bpm = int(tempo2bpm(units))
timing = int(units / bpm / 16)
# timing = units per 1/16 beat
except:
pass pass
self.addToClipboard(str(output_list)) self.addToClipboard(str(output_list))
def get_note_as_micro_bit_string(self, midi_msg):
note_value = midi_msg.note
octave = note_value // 12
tone = note_value % 12
return self.note_reference[tone] + str(octave)