craffel / pretty-midi

Utility functions for handling MIDI data in a nice/intuitive way.
MIT License
873 stars 151 forks source link

note filtering logic #199

Closed spyroot closed 3 years ago

spyroot commented 3 years ago

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.

[Note(start=3.750000, end=3.755208, pitch=36, velocity=127),
 Note(start=8.500000, end=8.505208, pitch=38, velocity=127), 
 Note(start=13.250000, end=13.255208, pitch=42, velocity=105)]

I think it somewhere below

   key = (event.channel, event.note)
                    if key in last_note_on:
                        # 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.
                        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]

I check all software that I have and all render MIDI files.

Noticed MIDO

<meta message track_name name='SessionPro_8Bars_01 edit\x00' time=0>
<meta message time_signature numerator=4 denominator=4 clocks_per_click=36 notated_32nd_notes_per_beat=8 time=0>
<meta message time_signature numerator=4 denominator=4 clocks_per_click=36 notated_32nd_notes_per_beat=8 time=0>
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=0.25
note_off channel=0 note=42 velocity=64 time=0
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
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
note_on channel=0 note=42 velocity=127 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=49 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=68 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=105 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=102 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=124 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=94 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=38 velocity=124 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
note_on channel=0 note=36 velocity=127 time=0.25
note_on channel=0 note=46 velocity=127 time=0
note_off channel=0 note=46 velocity=64 time=0
note_off channel=0 note=36 velocity=64 time=0.005208333333333333
note_on channel=0 note=36 velocity=127 time=0.24479166666666666
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=93 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
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=116 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=85 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=64 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=93 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=124 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
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=46 velocity=126 time=0
note_off channel=0 note=46 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=120 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=38 velocity=127 time=0.25
note_on channel=0 note=42 velocity=127 time=0
note_off channel=0 note=42 velocity=64 time=0
note_off channel=0 note=38 velocity=64 time=0.005208333333333333
note_on channel=0 note=36 velocity=127 time=0.24479166666666666
note_off channel=0 note=36 velocity=64 time=0
note_on channel=0 note=42 velocity=118 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=123 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=62 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=77 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=109 time=0
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=124 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=121 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
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
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=46 velocity=127 time=0
note_off channel=0 note=46 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=103 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=36 velocity=120 time=0.25
note_off channel=0 note=36 velocity=64 time=0
note_on channel=0 note=42 velocity=126 time=0
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=114 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=105 time=0.25
note_off channel=0 note=42 velocity=64 time=0.005208333333333333
note_on channel=0 note=38 velocity=127 time=0.24479166666666666
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
note_on channel=0 note=42 velocity=111 time=0.25
note_off channel=0 note=42 velocity=64 time=0
note_on channel=0 note=42 velocity=127 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=127 time=0
note_off channel=0 note=42 velocity=64 time=0
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
note_on channel=0 note=42 velocity=122 time=0.25
note_off channel=0 note=42 velocity=64 time=0
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=38 velocity=127 time=0.25
note_off channel=0 note=38 velocity=64 time=0
note_on channel=0 note=45 velocity=127 time=0
note_off channel=0 note=45 velocity=64 time=0
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=38 velocity=127 time=0.25
note_off channel=0 note=38 velocity=64 time=0
note_on channel=0 note=45 velocity=127 time=0
note_off channel=0 note=45 velocity=64 time=0
<meta message end_of_track time=0>
craffel commented 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.

spyroot commented 3 years ago

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

spyroot commented 3 years ago

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.

image

spyroot commented 3 years ago

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>
spyroot commented 3 years ago

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]