Skip to content

Commit 2712ce3

Browse files
committed
Autocorrect null notes, fix missing channels
1 parent 7cdfe0a commit 2712ce3

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

YTPMVE.py

+34-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ def exitScript(errMessage, exitCode,):
4040
def process_midi(MIDI_filename):
4141
A440_REF = 69 #MIDI index value of A4, the universal reference note.
4242

43+
counter=0
4344
current_time=0
4445
start=0
4546
MIDI_time=[]
@@ -60,6 +61,11 @@ def process_midi(MIDI_filename):
6061
#Process MIDI file
6162
print("Processing MIDI file.")
6263
try:
64+
MIDI_file_list = list(MIDI_file)
65+
# We must have a 1:1 ratio of note_offs for note_ons. This will create a space in note_durations which will be filled later.
66+
for i in range(len(MIDI_file_list)):
67+
note_durations.append("NULL")
68+
6369
for msg in MIDI_file:
6470
current_time=float(msg.time)+current_time
6571
# Change this so that we don't look at the if statement except the first few times.
@@ -71,14 +77,29 @@ def process_midi(MIDI_filename):
7177
continue
7278
else:
7379
MIDI_time.append(current_time)
74-
# End of note.
80+
# Start of note.
7581
if msg.type == "note_on" and msg.velocity != 0:
82+
counter += 1
7683
note_channels.append(msg.channel)
7784
note_tones.append(msg.note)
7885
note_starts.append(current_time)
79-
# We must have a 1:1 ratio of note_offs for note_ons. This will create a space in note_durations which will be filled later.
80-
note_durations.append("NULL")
81-
# Start of note
86+
87+
#Forward note search
88+
current_time_2 = current_time
89+
for counter_2 in range(1, len(MIDI_file_list)-counter):
90+
msg2 = MIDI_file_list[counter+counter_2]
91+
current_time_2 = current_time_2 + msg2.time
92+
#we need to confirm the type has the velocity attribute before checking if the velocity is 0, otherwise an error is thrown
93+
if msg2.type == "note_off" or msg2.type == "note_on":
94+
if msg2.type == "note_off" or (msg2.type == "note_on" and msg2.velocity == 0):
95+
note_duration = current_time_2 - current_time
96+
#Avoid zero-duration notes, which may cause crashes.
97+
if note_duration == 0:
98+
continue
99+
note_durations[counter] = note_duration
100+
break
101+
102+
# End of note
82103
elif msg.type == "note_off" or msg.velocity == 0:
83104
#note_durations.append(msg.time) #I think this was originally used for legato?
84105
# Reverse search the note starts list and find the note_on message that was probably linked to this note_off
@@ -88,6 +109,15 @@ def process_midi(MIDI_filename):
88109
list_match=i
89110
note_durations[list_match]=current_time-note_starts[i]
90111
break
112+
113+
#Forward search notes. This should probably be an optional feature, but for now it prevents notes from getting stuck on.
114+
# for i in range(0, len(note_starts), 1):
115+
# if note_durations[i] == "NULL":
116+
# try:
117+
# note_durations[i] = note_durations[i+1]
118+
# except IndexError:
119+
# pass
120+
91121
except Exception as error:
92122
exitScript(str(error)+". MIDI processing failed.", 1)
93123

YTPMVE_UI.pyw

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#YTPMVE
2-
#20250126
2+
#20250128
33
from os import path
44
import tkinter as tk
55
import tkinter.ttk as ttk
@@ -95,7 +95,8 @@ def set_midi_channel_titles(MIDI_file):
9595
track_name = msg.name
9696
#This might grab control changes unrelated to tracks? Not sure, may be an issue later and this should be refined.
9797
#Update 20250125: Only control change 0 is used for bank select, which serves a similar purpose to a program change.
98-
elif (msg.type == "control_change" and msg.control == 0) or msg.type == "program_change":
98+
#Update 20250128: Some horribly malformed MIDIs jump right into notes and never specify which channels are being used, so note_on, and note_off messages also add channels now.
99+
elif (msg.type == "control_change" and msg.control == 0) or msg.type == "program_change" or msg.type == "note_on" or msg.type == "note_off":
99100
channel = msg.channel
100101
if channel not in dict_midi_channels:
101102
dict_midi_channels[channel] = ('Channel {}: {}'.format(channel, track_name))

0 commit comments

Comments
 (0)