@@ -40,6 +40,7 @@ def exitScript(errMessage, exitCode,):
40
40
def process_midi (MIDI_filename ):
41
41
A440_REF = 69 #MIDI index value of A4, the universal reference note.
42
42
43
+ counter = 0
43
44
current_time = 0
44
45
start = 0
45
46
MIDI_time = []
@@ -60,6 +61,11 @@ def process_midi(MIDI_filename):
60
61
#Process MIDI file
61
62
print ("Processing MIDI file." )
62
63
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
+
63
69
for msg in MIDI_file :
64
70
current_time = float (msg .time )+ current_time
65
71
# 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):
71
77
continue
72
78
else :
73
79
MIDI_time .append (current_time )
74
- # End of note.
80
+ # Start of note.
75
81
if msg .type == "note_on" and msg .velocity != 0 :
82
+ counter += 1
76
83
note_channels .append (msg .channel )
77
84
note_tones .append (msg .note )
78
85
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
82
103
elif msg .type == "note_off" or msg .velocity == 0 :
83
104
#note_durations.append(msg.time) #I think this was originally used for legato?
84
105
# 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):
88
109
list_match = i
89
110
note_durations [list_match ]= current_time - note_starts [i ]
90
111
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
+
91
121
except Exception as error :
92
122
exitScript (str (error )+ ". MIDI processing failed." , 1 )
93
123
0 commit comments