Closed spyroot closed 3 years ago
Your MIDI file has lots of duration-zero notes:
note_on channel=0 note=36 velocity=125 time=0
note_off channel=0 note=36 velocity=64 time=0
This is a note off occurring 0 ticks after a note on - it is not a valid note and is ignored by pretty_midi
.
So I think it issues in re-presentation. It either a MIDO issue or something else.
How do you read time value? Because I can send this midi file and they do work in
5 or 6 programs I tested. it very short notes for drums. I had this issue that MIDO
converts a float to int so I'm not 100 positive that this time value MIDO
provides is correct.
Ableton / Cubabase / etc
For example.
This is in MIDO when you iterate
tempo = DEFAULT_TEMPO
for msg in merge_tracks(self.tracks):
# Convert message time from absolute time
# in ticks to relative time in seconds.
if msg.time > 0:
print(msg.time)
delta = tick2second(msg.time, self.ticks_per_beat, tempo) --> convert to time
else:
delta = 0
yield msg.copy(time=delta)
if msg.type == 'set_tempo':
tempo = msg.tempo
I put a print statement to see the actual delta time.
note_on channel=0 note=36 velocity=125 time=0
note_off channel=0 note=36 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0
note_off channel=0 note=42 velocity=64 time=0
48. <- delta time always how much current note need to wait. I put print directly in mido
So initial bar starts with two pitches 36 and 42.
both play for 0.25 ( sec or 48 ticks). note 42 kick in. I cross-check
with the editor and everything is correct.
note_on channel=0 note=42 velocity=35 time=0.25
note_off channel=0 note=42 velocity=64 time=0
48 <- again. pitch 42 play at next time event.
both 38, 42 play so current 42 will play
and stop at 0.25
So everything is correct. If you trace delta time. I can send files.
It commercial MIDI file for a studio.
note_on channel=0 note=38 velocity=127 time=0.25
note_off channel=0 note=38 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0
note_off channel=0 note=42 velocity=64 time=0
48
note_on channel=0 note=36 velocity=127 time=0.25
note_off channel=0 note=36 velocity=64 time=0
note_on channel=0 note=42 velocity=115 time=0
note_off channel=0 note=42 velocity=64 time=0
48
Check how Ableton renders that seq. If you check the time it correct seq.
Also in code, you calculate delta. ( I posted from MIDO from MidoFile Iterator ) so it actually seconds. If you iterate over the track you get delta and your delta is correct.
I really believe the issue in def _load_instruments(self, midi_data): it a bit massive method and hard to reason about. :)
# Convert tick values in midi_data to absolute, a useful thing.
for track in midi_data.tracks:
tick = 0
for event in track:
event.time += tick
tick = event.time
for track in midi_data.tracks:
tick = 0
for event in track:
print(event)
note_on channel=0 note=36 velocity=125 time=0
note_off channel=0 note=36 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=35 time=48
note_off channel=0 note=42 velocity=64 time=48
note_on channel=0 note=38 velocity=127 time=96
note_off channel=0 note=38 velocity=64 time=96
note_on channel=0 note=42 velocity=127 time=96
note_off channel=0 note=42 velocity=64 time=96
note_on channel=0 note=36 velocity=127 time=144
note_off channel=0 note=36 velocity=64 time=144
note_on channel=0 note=42 velocity=115 time=144
note_off channel=0 note=42 velocity=64 time=144
note_on channel=0 note=42 velocity=127 time=192
note_off channel=0 note=42 velocity=64 time=192
note_on channel=0 note=42 velocity=49 time=240
note_off channel=0 note=42 velocity=64 time=240
note_on channel=0 note=38 velocity=127 time=288
note_off channel=0 note=38 velocity=64 time=288
note_on channel=0 note=42 velocity=127 time=288
note_off channel=0 note=42 velocity=64 time=288
note_on channel=0 note=42 velocity=68 time=336
note_off channel=0 note=42 velocity=64 time=336
note_on channel=0 note=42 velocity=105 time=384
note_off channel=0 note=42 velocity=64 time=384
note_on channel=0 note=36 velocity=127 time=432
note_off channel=0 note=36 velocity=64 time=432
note_on channel=0 note=42 velocity=127 time=432
note_off channel=0 note=42 velocity=64 time=432
note_on channel=0 note=38 velocity=127 time=480
note_off channel=0 note=38 velocity=64 time=480
note_on channel=0 note=42 velocity=127 time=480
note_off channel=0 note=42 velocity=64 time=480
note_on channel=0 note=42 velocity=102 time=528
note_off channel=0 note=42 velocity=64 time=528
note_on channel=0 note=42 velocity=124 time=576
note_off channel=0 note=42 velocity=64 time=576
note_on channel=0 note=36 velocity=127 time=624
note_off channel=0 note=36 velocity=64 time=624
note_on channel=0 note=42 velocity=94 time=624
note_off channel=0 note=42 velocity=64 time=624
note_on channel=0 note=38 velocity=124 time=672
note_off channel=0 note=38 velocity=64 time=672
note_on channel=0 note=42 velocity=127 time=672
note_off channel=0 note=42 velocity=64 time=672
note_on channel=0 note=36 velocity=127 time=720
note_on channel=0 note=46 velocity=127 time=720
note_off channel=0 note=46 velocity=64 time=720
note_off channel=0 note=36 velocity=64 time=721
note_on channel=0 note=36 velocity=127 time=768
note_off channel=0 note=36 velocity=64 time=768
note_on channel=0 note=42 velocity=127 time=768
note_off channel=0 note=42 velocity=64 time=768
note_on channel=0 note=42 velocity=93 time=816
note_off channel=0 note=42 velocity=64 time=816
note_on channel=0 note=38 velocity=127 time=864
note_off channel=0 note=38 velocity=64 time=864
note_on channel=0 note=42 velocity=127 time=864
note_off channel=0 note=42 velocity=64 time=864
note_on channel=0 note=36 velocity=127 time=912
note_off channel=0 note=36 velocity=64 time=912
note_on channel=0 note=42 velocity=116 time=912
note_off channel=0 note=42 velocity=64 time=912
note_on channel=0 note=42 velocity=127 time=960
note_off channel=0 note=42 velocity=64 time=960
note_on channel=0 note=42 velocity=85 time=1008
note_off channel=0 note=42 velocity=64 time=1008
note_on channel=0 note=38 velocity=127 time=1056
note_off channel=0 note=38 velocity=64 time=1056
note_on channel=0 note=42 velocity=127 time=1056
note_off channel=0 note=42 velocity=64 time=1056
note_on channel=0 note=42 velocity=64 time=1104
note_off channel=0 note=42 velocity=64 time=1104
note_on channel=0 note=42 velocity=127 time=1152
note_off channel=0 note=42 velocity=64 time=1152
note_on channel=0 note=36 velocity=127 time=1200
note_off channel=0 note=36 velocity=64 time=1200
note_on channel=0 note=42 velocity=127 time=1200
note_off channel=0 note=42 velocity=64 time=1200
note_on channel=0 note=38 velocity=127 time=1248
note_off channel=0 note=38 velocity=64 time=1248
note_on channel=0 note=42 velocity=127 time=1248
note_off channel=0 note=42 velocity=64 time=1248
note_on channel=0 note=42 velocity=93 time=1296
note_off channel=0 note=42 velocity=64 time=1296
note_on channel=0 note=36 velocity=127 time=1344
note_off channel=0 note=36 velocity=64 time=1344
note_on channel=0 note=42 velocity=127 time=1344
note_off channel=0 note=42 velocity=64 time=1344
note_on channel=0 note=42 velocity=124 time=1392
note_off channel=0 note=42 velocity=64 time=1392
note_on channel=0 note=38 velocity=127 time=1440
note_off channel=0 note=38 velocity=64 time=1440
note_on channel=0 note=42 velocity=127 time=1440
note_off channel=0 note=42 velocity=64 time=1440
note_on channel=0 note=36 velocity=127 time=1488
note_off channel=0 note=36 velocity=64 time=1488
note_on channel=0 note=46 velocity=126 time=1488
note_off channel=0 note=46 velocity=64 time=1488
note_on channel=0 note=36 velocity=127 time=1536
note_off channel=0 note=36 velocity=64 time=1536
note_on channel=0 note=42 velocity=127 time=1536
note_off channel=0 note=42 velocity=64 time=1536
note_on channel=0 note=42 velocity=120 time=1584
note_off channel=0 note=42 velocity=64 time=1584
note_on channel=0 note=38 velocity=127 time=1632
note_on channel=0 note=42 velocity=127 time=1632
note_off channel=0 note=42 velocity=64 time=1632
note_off channel=0 note=38 velocity=64 time=1633
note_on channel=0 note=36 velocity=127 time=1680
note_off channel=0 note=36 velocity=64 time=1680
note_on channel=0 note=42 velocity=118 time=1680
note_off channel=0 note=42 velocity=64 time=1680
note_on channel=0 note=42 velocity=123 time=1728
note_off channel=0 note=42 velocity=64 time=1728
note_on channel=0 note=42 velocity=62 time=1776
note_off channel=0 note=42 velocity=64 time=1776
note_on channel=0 note=38 velocity=127 time=1824
note_off channel=0 note=38 velocity=64 time=1824
note_on channel=0 note=42 velocity=127 time=1824
note_off channel=0 note=42 velocity=64 time=1824
note_on channel=0 note=42 velocity=77 time=1872
note_off channel=0 note=42 velocity=64 time=1872
note_on channel=0 note=42 velocity=127 time=1920
note_off channel=0 note=42 velocity=64 time=1920
note_on channel=0 note=36 velocity=127 time=1968
note_off channel=0 note=36 velocity=64 time=1968
note_on channel=0 note=42 velocity=109 time=1968
note_off channel=0 note=42 velocity=64 time=1968
note_on channel=0 note=38 velocity=127 time=2016
note_off channel=0 note=38 velocity=64 time=2016
note_on channel=0 note=42 velocity=127 time=2016
note_off channel=0 note=42 velocity=64 time=2016
note_on channel=0 note=42 velocity=124 time=2064
note_off channel=0 note=42 velocity=64 time=2064
note_on channel=0 note=42 velocity=121 time=2112
note_off channel=0 note=42 velocity=64 time=2112
note_on channel=0 note=36 velocity=127 time=2160
note_off channel=0 note=36 velocity=64 time=2160
note_on channel=0 note=42 velocity=127 time=2160
note_off channel=0 note=42 velocity=64 time=2160
note_on channel=0 note=38 velocity=127 time=2208
note_off channel=0 note=38 velocity=64 time=2208
note_on channel=0 note=42 velocity=127 time=2208
note_off channel=0 note=42 velocity=64 time=2208
note_on channel=0 note=36 velocity=127 time=2256
note_off channel=0 note=36 velocity=64 time=2256
note_on channel=0 note=46 velocity=127 time=2256
note_off channel=0 note=46 velocity=64 time=2256
note_on channel=0 note=36 velocity=127 time=2304
note_off channel=0 note=36 velocity=64 time=2304
note_on channel=0 note=42 velocity=127 time=2304
note_off channel=0 note=42 velocity=64 time=2304
note_on channel=0 note=42 velocity=103 time=2352
note_off channel=0 note=42 velocity=64 time=2352
note_on channel=0 note=38 velocity=127 time=2400
note_off channel=0 note=38 velocity=64 time=2400
note_on channel=0 note=42 velocity=127 time=2400
note_off channel=0 note=42 velocity=64 time=2400
note_on channel=0 note=36 velocity=120 time=2448
note_off channel=0 note=36 velocity=64 time=2448
note_on channel=0 note=42 velocity=126 time=2448
note_off channel=0 note=42 velocity=64 time=2448
note_on channel=0 note=42 velocity=114 time=2496
note_off channel=0 note=42 velocity=64 time=2496
note_on channel=0 note=42 velocity=105 time=2544
note_off channel=0 note=42 velocity=64 time=2545
note_on channel=0 note=38 velocity=127 time=2592
note_off channel=0 note=38 velocity=64 time=2592
note_on channel=0 note=42 velocity=127 time=2592
note_off channel=0 note=42 velocity=64 time=2592
note_on channel=0 note=42 velocity=111 time=2640
note_off channel=0 note=42 velocity=64 time=2640
note_on channel=0 note=42 velocity=127 time=2688
note_off channel=0 note=42 velocity=64 time=2688
note_on channel=0 note=36 velocity=127 time=2736
note_off channel=0 note=36 velocity=64 time=2736
note_on channel=0 note=42 velocity=127 time=2736
note_off channel=0 note=42 velocity=64 time=2736
note_on channel=0 note=38 velocity=127 time=2784
note_off channel=0 note=38 velocity=64 time=2784
note_on channel=0 note=42 velocity=127 time=2784
note_off channel=0 note=42 velocity=64 time=2784
note_on channel=0 note=42 velocity=122 time=2832
note_off channel=0 note=42 velocity=64 time=2832
note_on channel=0 note=38 velocity=127 time=2880
note_off channel=0 note=38 velocity=64 time=2880
note_on channel=0 note=38 velocity=127 time=2928
note_off channel=0 note=38 velocity=64 time=2928
note_on channel=0 note=45 velocity=127 time=2928
note_off channel=0 note=45 velocity=64 time=2928
note_on channel=0 note=38 velocity=127 time=2976
note_off channel=0 note=38 velocity=64 time=2976
note_on channel=0 note=38 velocity=127 time=3024
note_off channel=0 note=38 velocity=64 time=3024
note_on channel=0 note=45 velocity=127 time=3024
note_off channel=0 note=45 velocity=64 time=3024
<meta message end_of_track time=3024>
I think I know where is the issue, if you are ok I can commit.
notes_to_close = [
(start_tick, velocity)
for start_tick, velocity in open_notes
if start_tick != end_tick]
notes_to_keep = [
(start_tick, velocity)
for start_tick, velocity in open_notes
if start_tick == end_tick]
You keep track last note on and that trigger note off.
note_on channel=0 note=36 velocity=125 time=0.-> goes to keep note_off channel=0 note=36 velocity=64 time=0 -> goes to keep note_on channel=0 note=42 velocity=127 time=0 -> goes to keep note_off channel=0 note=42 velocity=64 time=0 -> goes to keep.
note_on channel=0 note=42 velocity=35 time=48 -> this note ON event must remove from last note_off channel=0 note=42 velocity=64 time=48 -> or This ( depend on the logic)
Line 383 ( I move to separate method to a bit relax method itself)
elif event.type == 'note_on' and event.velocity > 0:
# before we add we check do we have note that need stop
print("Note len before", len(last_note_on))
self._finish_notes(event, last_note_on, __get_instrument, current_instrument, track_idx)
print("Note len after", len(last_note_on))
# store this as the last note-on location
note_on_index = (event.channel, event.note)
last_note_on[note_on_index].append((event.time, event.velocity))
# Note offs can also be note on events with 0 velocity
elif event.type == 'note_off' or (event.type == 'note_on' and
event.velocity == 0):
self._note_off_event(event, last_note_on, __get_instrument, current_instrument, track_idx)
def _note_off_event(self, event, last_note_on, __get_instrument, current_instrument, track_idx):
# Check that a note-on exists (ignore spurious note-offs)
key = (event.channel, event.note)
# Get the start/stop times and velocity of every note
# which was turned on with this instrument/drum/pitch.
# One note-off may close multiple note-on events from
# previous ticks. In case there's a note-off and then
# note-on at the same tick we keep the open note from
# this tick.
if key not in last_note_on:
return
end_tick = event.time
open_notes = last_note_on[key]
notes_to_close = [
(start_tick, velocity)
for start_tick, velocity in open_notes
if start_tick != end_tick]
notes_to_keep = [
(start_tick, velocity)
for start_tick, velocity in open_notes
if start_tick == end_tick]
print("Note to keep ", len(notes_to_keep), " note to close ", len(notes_to_close))
for start_tick, velocity in notes_to_close:
start_time = self.__tick_to_time[start_tick]
end_time = self.__tick_to_time[end_tick]
# Create the note event
note = Note(velocity, event.note, start_time, end_time)
# Get the program and drum type for the current
# instrument
program = current_instrument[event.channel]
# Retrieve the Instrument instance for the current
# instrument
# Create a new instrument if none exists
instrument = __get_instrument(program, event.channel, track_idx, 1)
# Add the note event
instrument.notes.append(note)
if len(notes_to_close) > 0 and len(notes_to_keep) > 0:
# Note-on on the same tick but we already closed
# some previous notes -> it will continue, keep it.
last_note_on[key] = notes_to_keep
elif len(notes_to_keep) > 0 and len(notes_to_close) == 0:
# Note off event doesn't cancel previous, so we keep it.
# on next Note On event this suppose to go out.
# Added this check. So current note-off event didn't close anything.
# we keep in the queue., next event On or Off if delta-time > that implies all pass event stop playing
last_note_on[key] = notes_to_keep
else:
# Remove the last note on for this instrument
del last_note_on[key]
This one triggered a note-on event. All notes that currently in the queue, still playing. We got Note ON event and it delta time > than an event in the queues.
Now we if you think about it event we keep only if we got a Note Off event, that implies that Note On Delta indicates stop playing.
def _finish_notes(self, event, last_note_on, __get_instrument, current_instrument, track_idx):
end_tick = event.time
notes_to_remove = []
for k, v in last_note_on.items():
start_tick, velocity = v[0]
_channel, _note = k
if end_tick > start_tick:
# start we know, end is current note on event
start_time = self.__tick_to_time[start_tick]
end_time = self.__tick_to_time[end_tick]
note = Note(velocity, _note, start_time, end_time)
program = current_instrument[_channel]
instrument = __get_instrument(program, _channel, track_idx, 1)
instrument.notes.append(note)
# we close a note we remove it.
notes_to_remove.append(k)
for key in notes_to_remove:
del last_note_on[key]
Hi,
I think filtering logic has an issue I have a bunch of midi files all polished but the instrument shows no pitches at all.
I think it somewhere below
I check all software that I have and all render MIDI files.
Noticed MIDO