2

I'm writing a deep learning automatic composer using RNN. Obviously i need to train it and I decided to use MIDI file format as input.

So far i wrote my input code and my model, but i had some problems reading the input MIDI.

This is my "reading" part of code:

from mydy import Events, FileIO, Containers
test=FileIO.read_midifile('file2.mid') #returns a Pattern with the MIDI file information (resolution ecc...), based on documentation https://github.com/jameswenzel/mydy/blob/master/src/FileIO.py
print(test) #I have to figure out how time is managed

Where i'm using this library which is the Python3 compatible version of this other one (which is only Python2 compatible)

The result i get is the following one:

 mydy.Pattern(format=0, resolution=96, tracks=\
[mydy.Track(relative: True\
  [mydy.TrackNameEvent(tick=0, text='', data=[]),
   mydy.TimeSignatureEvent(tick=0, data=[4, 2, 36, 8]),
   mydy.TimeSignatureEvent(tick=0, data=[4, 2, 36, 8]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[60, 100]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[64, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[60, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[62, 100]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[67, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[62, 64]),
   mydy.NoteOffEvent(tick=0, channel=0, data=[64, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[64, 100]),
   mydy.NoteOffEvent(tick=0, channel=0, data=[67, 64]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[64, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[67, 100]),
   mydy.NoteOnEvent(tick=384, channel=0, data=[66, 100]),
   mydy.NoteOffEvent(tick=0, channel=0, data=[67, 64]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[66, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[67, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[67, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[69, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[69, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[71, 100]),
   mydy.NoteOnEvent(tick=384, channel=0, data=[60, 100]),
   mydy.NoteOffEvent(tick=0, channel=0, data=[71, 64]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[60, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[62, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[62, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[64, 100]),
   mydy.NoteOffEvent(tick=375, channel=0, data=[64, 64]),
   mydy.NoteOnEvent(tick=9, channel=0, data=[67, 100]),
   mydy.NoteOnEvent(tick=384, channel=0, data=[66, 100]),
   mydy.NoteOffEvent(tick=0, channel=0, data=[67, 64]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[66, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[67, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[67, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[69, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[69, 64]),
   mydy.NoteOnEvent(tick=0, channel=0, data=[71, 100]),
   mydy.NoteOffEvent(tick=384, channel=0, data=[71, 64]),
   mydy.EndOfTrackEvent(tick=0, data=[])])])

Which is fine to me.

The problem is: how is MIDI tick managed? Is it a fixed value for each "type" of note?

For example, if i have a quarter note, i will always have (for example) 100 tick, indipendetly on the BPM of the original MIDI file?

For example, if i open a MIDI file written at 100 BPM in a DAW, and then i open a file written at 150 BPM, a quarter note will always correspond to 100 tick? (in both cases)

Since i have many midi files at different BPM, i obviously need a uniform representation of my input for my deep network.

I read the documentation but i'm a bit confused. Especially here when it says:

This message is important if the MIDI time division is specified in "pulses per quarter note", as such MIDI time division defines the number of ticks per quarter note, but does not itself define the length of the quarter note. The length of the quarter note is then defined with the set tempo meta message described here.

Mattia Surricchio
  • 1,362
  • 2
  • 21
  • 49
  • You've already answered the question of how many pulses per quarter note, the rest is probably covered by https://stackoverflow.com/questions/2038313/converting-midi-ticks-to-actual-playback-seconds – Pete Kirkham Apr 27 '20 at 09:29
  • @PeteKirkham So (if i'm not wrong) if i'm reading a MIDI file that gives 140 BPM when opened with a DAW or any sequencer, and a MIDI file at 100 BPM, i can just process them "uniformly"? By uniformly i mean that all i need is my tick per beat. A beat note from the 140BPM song will be the same as a beat from the 100BPM song (tickwise) – Mattia Surricchio May 02 '20 at 18:03
  • As Jules and the linked answer gives, four times the ticks per quarter note given in each file gives the ticks per beat, 60 divided by the BPM gives seconds per beat; if they both have the same value of 96 ticks then one song expects one tick to be 60/(4*96*100) seconds and the other 60/(4*96*140) seconds. If they have different values of ticks per quarter then the values change; if they have the same value and you play at the same tempo then the 140 BPM one will be slower than written. – Pete Kirkham May 03 '20 at 12:13

1 Answers1

3

The ticks per quarter note or "resolution" is a variable per file in MIDI, and given in the header of the file. Looks like the library you use is making it available to you as resolution=96.

The tempo (BPM) itself is embedded in the MIDI stream (along with the notes) as it can change at any point through the track. By default it is assumed to be 120 BPM.

You can find this information and lot more in the MIDI file spec, e.g. here: http://www.music.mcgill.ca/~ich/classes/mumt306/StandardMIDIfileformat.html

Jules Olléon
  • 6,733
  • 6
  • 37
  • 47
  • So (tell me if i'm wrong) i can basically import any MIDI file i want, the resolution/ticks per quarter notes all always the same right? I can just work over the ticks and then change the BPM (if needed) at the end of my process. I'm not sure if i can just discard all the information about BPM ecc... and just process my inputs by their ticks per beat – Mattia Surricchio May 02 '20 at 17:54
  • 1
    Depends if you want your RNN to learn about BPMs as well or not... tempo is an important part of music too! ;) – Jules Olléon May 03 '20 at 10:36
  • My idea was to just learn the note duration from the musical point of view, as in a piano sheets. For example, i would like my network to learn if a note from my MIDI file is a quarter note, half note ecc... ignoring the actual BPMs of the song, a quarter note is always a quarter note (indipendently from the BPM) If this is my goal (if i understood everything well) i can just work with the resolution and ticks per beat right? – Mattia Surricchio May 03 '20 at 12:52
  • 1
    Yes that should be sufficient. – Jules Olléon May 03 '20 at 13:38