Pitch-bend range
page200 opened this issue · 5 comments
In MIDI, the pitch-bend range is 2
by default, but can be modified via specific RPN messages, usually followed by specific "Data Entry" messages.
It would be nice to have functionality that understands those messages and can report the correct pitch or pitch-bend range.
As far as I understand, the pitch-bend range is set by three to four consecutive MIDI control messages. In hexadecimal, they look like this (with variables shown in bold):
B06500
B06400
B00602
B02604
The "0" after the "B" is the MIDI channel for which the pitch-bend range is being set.
The "02" in the end of the third message is the number of semitones by which the pitch can bend.
The "04" in the end of the fourth message is the number of cents to be added to the semitones.
The last message is optional, i.e. if there is no message of the form /B.26../ (like "B02604" in the example) then the number of cents is zero.
The pitch_bend_to_semitones
utility function already supports a different range than +/-2 semitones:
https://github.com/craffel/pretty-midi/blob/main/pretty_midi/utilities.py#L544
but we don't ever make use of that functionality in places where it would matter (e.g. when creating a piano roll or using fluidsynth). I agree it would be cool to keep track of these events and modify the piano roll/synthesis accordingly (assuming fluidsynth actually pays attention to these events?).
pyfluidsynth
assumes semitone_range=2
(see here) instead of paying attention to pitch-bend range messages. However, for existing MIDI files, midi2audio.FluidSynth
(which pays attention to pitch-bend range messages, as far as I remember) can be used instead. So no problem with FluidSynth.
The problem is to access correct pitch info in Python (as opposed to letting the compiled FluidSynth executable parse a MIDI file, which is probably what midi2audio.FluidSynth
does). Let's stick with your example - the piano roll:
pretty_midi does consider pitch bend in the piano roll, but it does that incorrectly in general because at https://github.com/craffel/pretty-midi/blob/main/pretty_midi/instrument.py#L150 it doesn't provide a second input argument to pitch_bend_to_semitones()
. So it defaults to semitone_range=2
instead of the correct semitone_range
from the pitch-bend range messages. Showing wrong pitch bend is kind of worse than not showing pitch bend.
Same during the other usage of pitch_bend_to_semitones()
, namely in synthesize()
at https://github.com/craffel/pretty-midi/blob/main/pretty_midi/instrument.py#L380
So yeah, it would be cool to keep track of pitch-bend range messages.
Yes, PRs are welcome.
So I looked into this, and it seems that mido
should be fixed in this regard first, right?
And then event_compare()
and so on. Regarding the comment "Events with the same tick time ares sorted by event type." there, is that sorting based on some official MIDI specification that should be followed or something?
And then event_compare() and so on. Regarding the comment "Events with the same tick time ares sorted by event type." there, is that sorting based on some official MIDI specification that should be followed or something?
It's just to make writing more predictable and testable, it doesn't follow and MIDI spec.