0

Im using the mido library on python to work with the midi file.

Given any midi file, I would like to output a midi file consisting only of the first 10 seconds of the input. I don't see any functions to do this in the library, so im trying to do this through going through each of the tracks.

Im finding a few things confusing. For example, below is what you get when you examine a single track in your midi object.

<meta message track_name name='Slow Strings' time=0>
program_change channel=0 program=49 time=0
program_change channel=0 program=49 time=0
control_change channel=0 control=7 value=71 time=0
control_change channel=0 control=10 value=75 time=0
note_on channel=0 note=55 velocity=89 time=15360
note_on channel=0 note=59 velocity=95 time=0
note_on channel=0 note=62 velocity=92 time=0
note_off channel=0 note=55 velocity=64 time=1324
note_off channel=0 note=62 velocity=64 time=12

So do I go through this list of messages in the track and count the time attribute until the running sum exceeds 10000 (milliseconds)? I don't think so, because looking at the piece on musescore, nothing significant haappens 15.36 seconds into the song.

I read here, that the times aren't in milliseconds, but delta times, which must be converted to milliseconds through PPQ (pulses per quater note). Is this correct, and if so is using a running sum of time the right approach to creating an output midi of time 10 seconds?

2
2

The times are not in milliseconds, they're in midi ticks which you can convert to seconds with the function tick2second(ticks, ticks_per_beat, tempo). Your code should look something like this:

from mido import MidiFile
from mido import tick2second

mid = MidiFile('input.mid')

for i, track in enumerate(mid.tracks):
    total_time = 0
    for msg in track:
        if msg.type == 'set_tempo':
            tempo = msg.tempo
        total_time  += tick2second(msg.time, mid.ticks_per_beat, tempo)
        print(msg, total_time) # or copy to output file
        if total_time > 10:
            break

Note: this assumes there are no tempo changes in the first 10 seconds of your input files. If there are your code will need to be more complex.

-1

If you're OK with C# instead of Python, you can use DryWetMIDI library. The code to take first 10 seconds of a MIDI file is super easy:

var midiFile = MidiFile.Read("My MIDI file.mid");
var newMidiFile = midiFile.TakePart(new MetricTimeSpan(0, 0, 10));
newMidiFile.Write("10sec version.mid");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.