diff --git a/lib/midi_management.py b/lib/midi_management.py index e11a238..a43f8d4 100644 --- a/lib/midi_management.py +++ b/lib/midi_management.py @@ -1,10 +1,11 @@ -from mido import MidiFile +from mido import MidiFile, tempo2bpm +import math import pyperclip as pc class MidiManagement: def __init__(self): - pass + self.note_reference = ['C', 'C#', 'D', 'D#', 'E', 'F', 'F#', 'G', 'G#', 'A', 'A#', 'B'] def addToClipboard(self, text): pc.copy(text) @@ -25,75 +26,56 @@ class MidiManagement: tracknumber += 1 output_list = [] + tracked_notes = [] + bpm = 0 + timing = 20000 + # Track messages for msg in mid.tracks[tracknumber]: - midi_msg = str(msg) - if midi_msg[0:8] == "note_on ": + if msg.type == "note_on": try: - msg_loc = midi_msg.index('note=') - 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)) + tracked_notes.append(self.get_note_as_micro_bit_string(msg)) except: pass - elif midi_msg[0:8] == "note_off": - ext_shortened = midi_msg[40:] - pos = 0 - for buchstabe in ext_shortened: - if buchstabe == "=": - pos += 1 - break - else: - pos += 1 - output = "R" - output += f":{pos}" + elif msg.type == "note_off": + # End tracked note at time offset for midi msg (that is relative to start) + note = '' + try: + note = self.get_note_as_micro_bit_string(msg) + except: + pass - timing_exp = ext_shortened[pos:] - output_list.append(output) + # Find note in tracked notes, ignore if not in there + 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: - pass + 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 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) +