[LAU] command line midi processing

Maurizio Berti maurizio.berti at gmail.com
Thu Aug 30 02:44:42 CEST 2018


Well, there is python-midi, which is stable enough:
https://github.com/vishnubob/python-midi/

You can easily create a script that automatically "shifts" the timing of
events by decreasing the tick of the first event.
By "easily" I imply some basic rules:
- all events which have to be shifted must be on the same midi track
- the first Note event in any of those tracks should not be at the very
beginning of the file
- tempo changes, if any, should not be too big

Of course, it's possible to do the same even with these limitations, but it
will be much more difficult to implement it in the right way.

Timing in midi files works with "ticks" or "pulses", and each file has its
own resolution, which represents the tick resolution per beat, or the
smallest possible quantization: if a midi file has a resolution equal to
128 it means that the smallest possible division is a 128th of a quarter
note.

The python-midi module treats midi files as nested lists. The main object,
representing the midi file read (or to be written), is a Pattern, which is
a list of Tracks, which in turn is a list of MidiEvents.

A very basic example, assuming you know the exact structure of your midi
file and you want to shift the second track:

import midi
pattern = midi.read_midifile('myfile.mid')
strings = pattern[1]
#let's see what's the next event with a positive relative tick
eventId = 0
event = strings[eventId]
while not event.tick:
    eventId += 1
    event = strings[eventId]
#ensure that the resulting tick is >= 0
firstEvent.tick = max(0, firstEvent.tick - 150)
midi.write_midifile('newfile.mid', pattern)

Sometimes midi files contain an "invisible" track which includes some
metadata; if you know the track name (and there are no duplicate names),
you can find it like this:

import midi
pattern = midi.read_midifile('myfile.mid')
#the TrackName event _should_ be the first event in the track...
for track in pattern:
    for eventId, event in enumerate(track):
        if isinstance(event, midi.TrackNameEvent) and event.text ==
'Strings':
            break
eventId += 1
event = track[eventId]
while not event.tick:
    eventId += 1
    event = track[eventId]
event.tick = max(0, event.tick - 150)
midi.write_midifile('newfile.mid', pattern)

These are very simple examples, with no error checks at all.
Also, the 150 subtraction is arbitrary, and it should be computed according
to the tempo and the tick resolution, which is accessible using
pattern.resolution; supposing that your file has a resolution of 600 ticks
per beat, the above examples will anticipate every event by a 16th, or
0.125 seconds if the tempo is set to 120bpm.
Once you've found out what's the preferred anticipation in seconds of your
patch, you could compute the right timing in the script also: Tempo events
are usually in the first track, so just cycle through it until you find a
SetTempoEvent, and compute the "delta tick" like this:

deltaSecs = 0.125
deltaTick = int(deltaSecs * pattern.resolution * tempoEvent.bpm / 60.)
[...]
firstEvent.tick = max(0, event.tick - deltaTick)

I hope this helps!

MaurizioB


2018-08-29 22:30 GMT+02:00 Francesco Ariis <fa-ml at ariis.it>:

> Hello LAU,
>     lately I have been playing with ABC notation [1].
> ABC outputs to postscript/PDF and MIDI (a good output), but there
> some things I would like to change in automatic fashion. Example:
> anticipate the attack on some channels (string).
> Is there a command line Linux utility to mess with midi files,
> similar to what ImageMagick is for images?
> I know plenty of libraries in many programming languages, but before
> diving into those I would like not to reinvent the wheel.
>
> [1] http://trillian.mit.edu/~jc/music/abc/doc/ABCtut_Intro.html
> _______________________________________________
> Linux-audio-user mailing list
> Linux-audio-user at lists.linuxaudio.org
> https://lists.linuxaudio.org/listinfo/linux-audio-user
>



-- 
È difficile avere una convinzione precisa quando si parla delle ragioni del
cuore. - "Sostiene Pereira", Antonio Tabucchi
http://www.jidesk.net
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.linuxaudio.org/archives/linux-audio-user/attachments/20180830/70548155/attachment.html>


More information about the Linux-audio-user mailing list