tags:

views:

297

answers:

1

I'm currently implementing an application to perform some tasks on MIDI files, and my current problem is to output the notes I've read to a LilyPond file.

I've merged note_on and note_off events to single notes object with absolute start and absolute duration, but I don't really see how to convert that duration to actual music notation. I've guessed that a duration of 376 is a quarter note in the file I'm reading because I know the song, and obviously 188 is an eighth note, but this certainly does not generalise to all MIDI files.

Any ideas?

+2  A: 

By default a MIDI file is set to a tempo of 120 bpm and the MThd chunk in the file will tell you the resolution in terms of "pulses per quarter note" (ppqn).

If the ppqn is, say, 96 than a delta of 96 ticks is a quarter note.

Should you be interested in the real duration (in seconds) of each sound you should also consider the "tempo" that can be changed by an event "FF 51 03 tt tt tt"; the three bytes are the microseconds for a quarter note.

With these two values you should find what you need. Beware that the duration in the midi file can be approximate, especially if that MIDI file it's the recording of a human player.

I've put together a C library to read/write midifiles a long time ago: http://middl.googlecode.com in case it may be helpful (it's quite some time I don't look at the code, feel free to ask if there's anything unclear).

I would suggest to follow this approach:

  1. choose a "minimal note" that is compatible with your division (e.g. 1/128) and use it as a sort of grid.
  2. Align each note to the closest grid line (i.e. to the closest integer multiple of the minimal node)
  3. Convert it to standard notation (e.g a quarter note, a dotted eight note, etc...).

In your case, take 1/32 as minimal note and 384 as division (that would be 48 ticks). For your note of 376 tick you'll have 376/48=7.8 which you round to 8 (the closest integer) and 8/32 = 1/4.

If you find a note whose duration is 193 ticks you can see it's a 1/8 note as 193/48 is 4.02 (which you can round to 4) and 4/32 = 1/8.

Continuing this reasoning you can see that a note of duration 671 ticks should be a double dotted quarter note.

In fact, 671 should be approximated to 672 (the closest multiple of 48) which is 14*48. So your note is a 14/32 -> 7/16 -> (1/16 + 2/16 + 4/16) -> 1/16 + 1/8 + 1/4.

If you are comfortable using binary numbers, you could notice that 14 is 1110 and from there, directly derive the presence of 1/16, 1/4 and 1/8.

As a further example, a note of 480 ticks of duration is a quarter note tied with a 1/16 note since 480=48*10 and 10 is 1010 in binary.

Triplets and other groups would make things a little bit more complex. It's not by chance that the most common division values are 96 (3*2^5), 192 (3*2^6) and 384 (3*2^7); this way triplets can be represented with an integer number of ticks.

You might have to guess or simplify in some situations, that's why no "midi to standard notation" program can be 100% accurate.

Remo.D
I corrected the link to my library and added some examples.
Remo.D
Thanks for the explanations, multiples of the integer nearest to duration/ticks seem to do the job. This turns out to be way more complicated than I expected, since some notes need to be split across measures -- I expected LilyPond would handle that, but it does not.
Anthony Labarre
If Lilypond is not a strict requirement, and you just need a way to print a score, have a look at ABC (http://abc.sourceforge.net) or pmw (http://www.quercite.com/pmw.html) they might be easier to use than Lilypond.
Remo.D
Sorry for not answering earlier. Thanks for suggesting ABC, it seems like a better pick for my app, and I'll probably stick to that. But while I'm here, I should add that LilyPond actually handles splitting notes, but not rests.
Anthony Labarre