Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling overlapping notes #163

Open
cifkao opened this issue Mar 5, 2019 · 1 comment
Open

Handling overlapping notes #163

cifkao opened this issue Mar 5, 2019 · 1 comment

Comments

@cifkao
Copy link

cifkao commented Mar 5, 2019

When an instrument has notes overlapping in time and pitch, PrettyMidi.write puts all of them in one channel, so some of them get clipped. E.g.:

In [2]: pm = pretty_midi.PrettyMIDI()
In [4]: pm.instruments.append(pretty_midi.Instrument(0))
In [5]: pm.instruments[0].notes[:] = [pretty_midi.Note(start=0., end=1., pitch=60, velocity=100), pretty_midi.Note(start=0.5, end=1.5, pitch=60, velocity=100)]
In [6]: pm.write('/tmp/test.midi')
In [7]: pretty_midi.PrettyMIDI('/tmp/test.midi').instruments[0].notes
Out[7]: 
[Note(start=0.000000, end=1.000000, pitch=60, velocity=100),
 Note(start=0.500000, end=1.000000, pitch=60, velocity=100)]

This might be surprising, at least to someone without an advanced knowledge of MIDI. PrettyMIDI should issue a warning when such overlapping notes are encountered. Even better, it could either (a) fix the problem by writing the notes to different channels automatically, or (b) provide a method to add additional instruments to the PrettyMIDI object and split the overlapping notes between them.

@craffel
Copy link
Owner

craffel commented Mar 5, 2019

This is caused by pretty_midi's parsing logic, which intentionally closes all open notes of a given pitch when it sees a note off for that pitch (all on the same channel, of course):
https://github.com/craffel/pretty-midi/blob/master/pretty_midi/pretty_midi.py#L316
This is an issue with the MIDI format, which you are using as intermediate because you are writing it out and then reading back in. There's no way to disambiguate between ending the first note on or second note on in the MIDI format. pretty_midi's convention is to end all the notes. Another convention could be LIFO, or FIFO, or something, but pretty_midi does not implement that at this time. It might be useful to have those behaviors as options when parsing MIDI files.

PrettyMIDI should issue a warning when such overlapping notes are encountered.

I am fine with adding a warning but it may get verbose. It's probably better to just make sure this behavior is well-documented.

(a) fix the problem by writing the notes to different channels automatically

I think this could get ugly quickly if there are many overlapping notes at once.

(b) provide a method to add additional instruments to the PrettyMIDI object and split the overlapping notes between them.

I don't like this solution either because it would break the conceptual model -- for example, I'd have to make sure that I run get_piano_roll on all of the relevant Instruments and sum them together, or something.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants