Midi time to milliseconds?
Posted 08 March 2007 - 03:28 PM
I'm writing some stuff using midi files and I need to convert the midi time stamps for each midi event into milliseconds. I've searched the web and every document I come across blathers on about quarter notes, tempo, beats per minute, measures, bars, ticks, metronomes, clocks per click, midi this and midi that... not being a musician I'm utterly confused. So can anyone tell me, in language a simpleton (ie ME) can understand, what numbers and formulas I need to convert the midi time to milliseconds?
Any help is most appreciated...
Posted 08 March 2007 - 05:03 PM
The MIDI header chunk contains a 16-bit value that gives the number of ticks per quarter note. (Ticks are the units measured by the delta-time values). This value is a constant over the whole file. Within the MIDI data stream are tempo meta-events, which contain a 24-bit value that give the number of microseconds per quarter note. Divide this one by the first one, and you get the number of microseconds per tick, which should be what you want. Note that the track may contain multiple tempo events, since the tempo frequently changes in the middle of a piece.
Now for a basic music lesson. The fundamental time unit of music is the beat. Beats can be slower or faster depending on the kind of music, and the tempo (speed of the beats) can change even in a single piece as I mentioned. Tempos in standard music notation are typically given in beats per minute.
Beats are organized into measures, also called bars (since they are separated by vertical bars in music notation). The number of beats per measure is usually 2, 3, 4, or 6. The majority of music is in 4, while for example a waltz would be in 3. The top number (numerator) of a time signature is the number of beats per measure. (The denominator indicates which note length gets one beat, which is normally a quarter note.)
Notes come in different power-of-two lengths. A quarter note normally is one beat long (although this isn't always the case). A half note is two beats, and a whole note is four beats. (It's called a whole note because it takes up a whole measure, if you're in 4.) An eighth note is half a quarter note, so there are two eighth notes per beat, a sixteenth note is half an eighth so there are 4 sixteenths per beat, and so on.
Hope this helps, and if you're going to be doing any significant processing of MIDI files, I would highly recommend learning a little basic music theory...it will help you understand what you're doing.
Posted 08 March 2007 - 05:40 PM
Too late... brain switched off... going home... back tomorrow...
Posted 16 March 2007 - 04:10 PM
I've got my midi sequencer just about working, but I've got a strange quirk... my midi events always seem to be half a beat off. I've looked through all the maths about twenty times and I cannot for the life of me see how totally different files can be exactly half a beat out with totally different midi events, tempos and divisions and whatnot. The sequences match up to the music perfectly but for this problem. So, I can only assume that the midi times are half a beat out. It's almost as if the beat times hit the middle of the beat duration, rather than the start of the beat, if you see what I mean. But I've never seen any mention of this anywhere so I'm dubious. I've fudged it by just adding half a beat to all the midi times and now everything seems to be fine. But I HATE fudges...
Has anybody else ever had this sort of trouble?
Posted 19 March 2007 - 09:35 AM
Now it all matches fine in the music sequencer, so there's nothing wrong with the data, but when I calculate the time of the midi events, my note markers appear half a beat off (actually half a beat early). So, obviously I'm doing something wrong. If it were simply a delay playing the mp3 file, then I don't see how would it always be half a beat off with music of varying tempos. I've looked at my time conversion code and the events seem to be at the correct tempo.
Here's my conversion code (with an extra half beat (division/2) added to the midi event time to fix the problem):
I need the event's game time in milliseconds. s_MidiStartTime is the game time when I started playing the mp3 file.
Like I said it works fine by adding half a beat, it just bothers me that I have to do that!
Posted 19 March 2007 - 05:21 PM
Also, you are aware that the MIDI event timestamps are *delta* times, i.e. the time since the previous event, not the time since the beginning of the file? It doesn't look in that equation you posted you are adding the time to the time of the previous event, but to the start time of the whole MIDI file.
Posted 20 March 2007 - 10:13 AM
When it loads the midi file it adds the previous event time to the current event time, to take into account the running status conditions in Midi files, and to avoid having to do that stuff at run time. So all the event times are made relative to the start of the midi file at load time. Then after it's calculated the relative milliseconds since I started playing, it adds the start time to get (supposedly) the game time for that event.
I've tried using your equation, it's very sensible and logical and I understand your thinking, but I can't get it to work. I know it should, and it's only one line of code so the potential for bugs is limited. I don't understand it myself either!
I'm getting pretty frustrated with myself for taking so long over this, it's only a simple time conversion after all... GRRRRRRR... obviously I'm just fundamentally misunderstanding something. I'll have to stick with my cumbersome equation for the moment and get on with something else before I chuck the PC out the window, come back to it later with a fresh mind. But many thanks for giving me your help on this anyway!
Posted 20 March 2007 - 02:53 PM
When it loads the midi file it adds the previous event time to the current event time, to take into account the running status conditions in Midi files, and to avoid having to do that stuff at run time.
Note that doing it that way could cause trouble if the tempo changes in the middle of the file. (Which it seems might be likely if your midi-files are constructed to synchronize mp3s, as real live performers don't hold to a precise constant tempo even when they mean to.) Also, it could be that the tempo is only set once, but the tempo event does not come till a short time after the beginning of the file - maybe this is the source of your half beat offset?
Posted 02 July 2008 - 06:44 PM
Now my problem doesn't seem to be with converting from ticks to milliseconds (seems to work fine), but rather from milliseconds to ticks:
def ms(time, tempo, division = 96): #from ticks division *= 1.0 if isinstance(tempo, list): ms = 0 tempos = len(tempo) for i, t in enumerate(tempo): if i+2 > tempos: end = time else: end = tempo[i+1] if end > time: end = time if t < time: ms += (end - t) * t / division return ms / 2000 return time * tempo/(division * 2000) def ticks(time, tempo, division = 96): #from ms division *= 1.0 if isinstance(tempo, list): new =  for t in tempo: new += [(ms(t, tempo, division), t)] ticks = 0 tempos = len(new) for i, t in enumerate(new): if t < time: if i+2 > tempos: end = time else: end = new[i+1] if end > time: end = time ticks += (end - t) * division / t else: break return ticks * 2000 return time * (division * 2000)/tempo
As you can see, the tempo's time-codes were in ticks so the first thing the ticks method did was change them to ms. Also, you can see that instead of dividing (or in the ticks method, multiplying) by 1000 I did it by 2000. I have no idea why, but when making the ms method I found that the length of every song exactly 2x as long as they should have been.
If you don't know python, basically all they do are convert each "tempo section" separately until the time that was input, then add them together. t would be time, while t would be tempo.
Any ideas of what's wrong? I have absolutely no idea at this point.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users