craffel / pretty-midi

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

Multitude of set_tempo messages after PrettyMIDI.adjust_times #223

Closed almostimplemented closed 1 year ago

almostimplemented commented 1 year ago

I've been using pretty_midi to align the audio and MIDI of the solo jazz piano performances from the RWC Music Database. I have had a couple problems, which I will break into two GitHub issues. (The other is #224).

Note: I am aiming for fine-alignment, so my hop size is 64 (default is 512).

(By the way, I am very happy to either deal with this on my own or attempt a pull-request. Consider this a humble request for your advice, @craffel !)

This issue is about the fact that the newly aligned MIDI file has a very high number of set_tempo events. Even if I take the RWC MIDI and "normalize" it to remove all set_tempo messages (while attempting to retain the same absolute times of all note events), the results of align_midi.py have tens of thousands of tempo changes:

>>> import mido
>>> len([msg for msg in mido.MidiFile("norm_RM-J001.MID") if msg.type == "set_tempo"])
0
>>> len([msg for msg in mido.MidiFile("norm_RM-J002.MID") if msg.type == "set_tempo"])
0
>>> len([msg for msg in mido.MidiFile("norm_RM-J004.MID") if msg.type == "set_tempo"])
0
>>> len([msg for msg in mido.MidiFile("aligned_RM-J001.MID") if msg.type == "set_tempo"])
58730
>>> len([msg for msg in mido.MidiFile("aligned_RM-J002.MID") if msg.type == "set_tempo"])
102297
>>> len([msg for msg in mido.MidiFile("aligned_RM-J004.MID") if msg.type == "set_tempo"])
47518

Is this really necessary when the input MIDI has a constant tempo? It's not exactly a "bug" but it seems, with constant tempo, we should be able to simply interpolate all the MIDI events based on the warping path no? Am I missing something?

Repro files: https://drive.google.com/drive/folders/1IWjpAW0yR8U3yRz1a_-T8ncsmI_OkE6n?usp=share_link

craffel commented 1 year ago

If both the MIDI file and the audio file have constant tempo, it's possible that you could have a single tempo change event, but (using the provided algorithm) that would mean that the alignment process worked perfectly (and without quantization error), which it almost certainly doesn't. If you do have a MIDI and audio file with constant tempo, you probably should create a separate special-case alignment algorithm that doesn't handle fluidly-varying timing. There is in principle nothing wrong with a MIDI file that has tens or hundreds of thousands of tempo change events.