I have developed a Midi Player and have issues computing the overall length (in quarters) of Midi Files exported by Logic Pro X (SMF Format 1).
So far I calculated the length of a Midi file by determining the time for the "End of Track" for each track (including Track 0 - Tempotrack) and determining the longest one.
This worked fine, except for midi files exported by Logic. These files contain in track 0 (Tempo Track) an "End of Track" command at an extremely late time (about 8000 quarters), which turns a 4 min file into a 1 hour file.
The rest of the tracks, which contain the actual Midi events, have a correct "End of track" time ...
Now to my question: Can I ignore the tempo track for calculating the song length? Unfortunately, I can not find anything in the Midi Song Specs.
Hello,
Hmm, I have, from time to time, found midi files with a spurious length, which seems to have been due to an End of Track event which is way past the REAL the musical EOT. I've never understood where this comes from. I've assumed the file has been edited in some way, or not saved correctly, maybe Logic is to blame here too?
The EoT event is not really important, although the midi spec requires it, and most software systems expect it, and will complain if it's not there.
For your purposes, I would suggest that you disregard it, and instead use the immed previous timed event (i.e. the last note event, or the last midi controller, or whatever). I assume that as far as the TEMPO track you refer to is concerned, there are no other events between the EoT of the other tracks and the EoT of the Tempo track? I would guess that there are none.
Could you post one of the files with this in. I'd like to have a look at the data in the file.
Geoff
My understanding is the method you described is the correct method to determine the length of the music in the MIDI file: Calculate the time positions of all the End of Track events in the file, including the tempo track, and use the latest one.
I found posts on a Logic Pro forum that describe when you export a small MIDI section from a large Logic project, the resulting MIDI file has the length of the entire Logic project but only contains the notes selected for export in the same place as they were in the original project, with empty space before and after it:
[list]
The Standard MIDI File specification only says the following (see The Complete MIDI 1.0 Detailed Specification, PDF page 138):
End of Track
This event is not optional. It is included so that an exact ending point may be specified for the track, so that it has an exact length, which is necessary for tracks which are looped or concatenated.
If you anticipate the users of your MIDI player will often use files exported from Logic or other files with lots of silence on the end, you might add an option to trim excessive silence from the end of the playback. However, you may want this to be an option that can be turned off if desired. If your MIDI player has the ability to play multiple MIDI files in a playlist or to loop a single MIDI file, there could be cases where a user would want the silence at the end of the file to be played exactly as long as the MIDI file specifies.
I have attached 2 simple Midi Files directly exported by Logic where i have set the Project Start to 1.1.1.1 and the Project End to 3.1.1.1.
the first file (ex1.mid) just contains a Tempo Track and 2 Midi Tracks with a few midi note events. The 2 Midi Tracks have a correct EOT Message at 8 quarters. But the EOT Message of the Tempo Track is 8000 quarters...
The second file (ex2.mid) contains the same data as the first file with the same Project Start/End Settings. Additionaly i inserted a tempo Change at 9.1.1.1 (behind the Project End).
Logic exported the same EOT Messages like in the first file...
Is this a Logic Pro Bug?
I never had problems with other downloaded Midi Files or Cubase exports.
My problem is,
i could just ignore the EOT Message of the Tempo Track and use the other EOT Messages for calculating the song length.
But could there be use cases, where the tracks with midi events end, but there are still Tempo Changes after the last Midi Events (for example to control external devices with MIDI Clock) ?
Hello,
Thanks for the two example files. Interesting.
I could not say that this is a 'bug', there may well be a valid reason for the software doing this. Just that it seems totally irrelevant in the case of your files. And the tick setting is quite out of proportion!
I attach two 'decode' .TXT files for your information. In the first, the EoT item for Tr 1 is near the start of the file, and for some reason no Time/Bar value has been generated, so that line has stayed there because of the 0.000 bar time. Adds to the confusion. I need to look up why that might be.
In the second file, the bar time HAS been generated, so this item moves to the bottom of the file.
In either case, there is clearly nothing between the last real midi event and the EoT, so the EoT timing data could be changed to reflect the musical facts. Do you have a means of doing that?
In the second file, the extra tempt item you've added in also, in effect, does nothing at all as there is no data afterwards.
In either case, the midi file could/should END just after 2.001.
As Bavi suggests, there are reasons why you MIGHT need the space to be preserved, such as the data looping, but to be honest I've never seen a midi file that uses looping.
Has anyone seen such a thing?
Geoff
Just a follow up to the previous notes.
Just looking at the data again. I'm wondering what the SMPTE item is there for, and why it's showing what I suspect is a very large offset. If the numbers mean what I suspect they do, this is showing an offset of 33 hours. Might there be some connection between this SMPTE setting, and the problem you describe? Do you still get the problem if there is no SMPTE offset defined?
Geoff
I've never seen a midi file that uses looping.
Be aware that there's not a standard way to indicate that a MIDI file "uses looping" within the file itself.
However, some kinds of short music might make sense to loop, like some kinds of video game music or a ringtone. If you are using a MIDI player that has an option to loop the entire file, you might want to loop these kinds of MIDI files if desired.
In a case like that, imagine that an End of Track event indicates the music ends with a measure of one quarter note and three quarter rests. Ignoring the End of Track event and looping after the quarter note would mess up the beat. Obeying the End of Track event and looping after the three quarter rests would preserve the beat.
I attach two 'decode' .TXT files for your information.
Geoff, be aware that the program you use to convert MIDI files to text seems to have the following issues:
1. When it converts a position in ticks to a position in seconds, the precision of the calculations seems to be a little bit off.
In your text files, the events labeled with "2.001" seconds are really at 2 seconds exactly, and the events labeled with "4.001" seconds are really at 4 seconds exactly. In the second file, the tempo event labeled with "16.255" seconds is really at 16.25 seconds.
2. When it converts a position in ticks to a position in seconds, it seems to have a problem handling a large number of ticks.
In the first example, it looks like the program couldn't handle the large number of ticks of the first track's End of Track position (3,840,000 ticks) and defaulted to a position of zero seconds.
In the second example, there are two tempos. When the program attempted to convert the first track's End of Track position (also 3,840,000 ticks) to seconds, it looks like the program was able to calculate an amount of seconds for the range covered by the first tempo, but when it tried to add the amount of seconds for the range covered by the second tempo, it seems to have failed to calculate that and used zero instead. So the sum of the two ranges ended up just being the position of the second tempo event.
3. When it displays an SMPTE Offset meta event, it is incorrectly displaying the entire first byte as an hours value ("33 hours") instead of correctly interpreting the high bits as indicating the time code type (time code type is 25 frames per second and hour value is 1 hour).
Hello Bavi,
Thanks for your notes about the DECODE program.
The package of which this prog is a part dates back to 1991, so I guess it's pretty ancient now. However, I use various of the parts of the system quite a lot, and I find it useful.
I'll make some notes in the manual to reflect your comments, which will be very useful.
Regarding the details, I'm not sure if the calculation is off, it may JUST be that the rounding on the display of the numbers is off. In some places within parts of the system the bar time is displayed with two decimal places, in others (like DECODE) it's displayed with three decimal places. I'd guess that in some cases the calculated value may have more places? The rounding OUGHT to be consistent though, and clearly it is not. The values that show as 2.001 and 4.001 are possibly misleading. If a value shows as - say - 4.123 and it OUGHT to be 4.122 then this may be a lot less important?
Clearly, the program does NOT cope with the VERY large delta time, and fails to convert it to bar time. I'm not sure what bar time 3.8m might convert to, but this again may be outside the limits of the print formatting??
As for the SMPTE, when did the spec change to allow for the use of the hight bits in the 'days' value for 'time code type'. Was this parameter active when the software was written in 1991/2. Yes, I fully accept that my reference to an offset of 33 days will be wrong, and the offset should actually be 1 day, but I would still wonder if the offset of even ONE day may be causing (even in part) the problem that OP is finding with the track length?
Thanks again.
Geoff
Hello Sebastian,
Just re-read your original message, and I note that you say that the file becomes about 1 hr when it ought to be much shorter.
I was asking about the SMPTE, and we have now determined that the setting in that will be about 1 hour also. So maybe there IS a connection between the SMPTE and the excessive EoT time?
Can you remove the SMPTE within Logic, and resave the file?
By the way, I've tried the ex1.mid file in a couple of midi players, and they play the file fine, and seem to take no notice at all of the SMPTE, and the spurious EoT time. They treat the file as being 3 seconds (or thereabouts) and play it happily. Then finish.
I've not done so, but I suspect that if I loaded this file into a midi player I've written, it would happily accept the data, but on playing it would continue to 'run' (in effect doing a lot of nothing) between the last actual note and the EoT (1). Of course I might quickly determine that there was nothing there to play and ESC, so no big deal. I should tweak my prog to safeguard against this??
Geoff
I've tried the ex1.mid file in a couple of midi players, and they play the file fine, and seem to take no notice at all of [...] the spurious EoT time. They treat the file as being 3 seconds (or thereabouts) and play it happily. Then finish.
I noticed the same thing in some MIDI players I use: playback ends after the last note (or other non-meta MIDI event). Although I feel it's technically correct to play until the End of Track event is reached in all tracks, there are some MIDI players that end playback after the last non-meta MIDI event is completed.
Plays until End of Track is reached in all tracks: Sekaiju, VLC Media Player.
Plays until last non-meta MIDI event is completed: Windows Media Player, Notation Player, Cakewalk by BandLab.
I've tried the ex1.mid file in a couple of midi players, and they play the file fine, and seem to take no notice at all of the SMPTE [...].
I think the SMPTE Offset is only used if your MIDI player is able to sync with a tape system. Something like you start the tape and once the timecode on the tape matches the SMPTE Offset value, the MIDI file will start. A MIDI player designed for just listening to MIDI files doesn't need to do anything with the SMPTE Offset.
I fully accept that my reference to an offset of 33 days will be wrong, and the offset should actually be 1 day
about the SMPTE, [...] we have now determined that the setting in that will be about 1 hour
Note that the SMPTE Offset in the examples is exactly 1 hour (not 1 day). Evidently, a timecode of 1 hour is commonly used as a starting point in video production. See Video Production Stack Exchange Why does all timecode start at 1 hour? (01:00:00:00).
As for the SMPTE, when did the spec change to allow for the use of the hight bits in the 'days' value for 'time code type'. Was this parameter active when the software was written in 1991/2.
Hm, I don't know. I don't use SMPTE time myself, but when I noticed the SMPTE Offset hour value in a sequencer I use was different than the hour value in text file you made, I peeked in the specs to see what could be going on.
The part about the hours field format is referenced in the Standard MIDI Files section of the Complete MIDI 1.0 Detailed Specifications but does not explain it there. You have to refer back to the special section called MIDI Time Code to see that the format for the hour is 0ffhhhhh where ff is the frame format of 00=24, 01=25, 10=30 Drop Frame, and 11= 30 Non-Drop. The bottom 5 bits are left for encoding the hours (0-31).
3840000 ticks at 480 tpq and a division of 500000 (120 BPM) is a delta time of 4000000 milliseconds or 4000 seconds. That equates to 1 hr 6 minutes and 40 seconds.
As for when that was added, the MIDI Time Code document section carried copyright dates of 1987, 1991, and 1994 so it has been that way since at least 1994 and perhaps earlier.
Update: On the Wayback Machine archive, I found a copy of the original MIDI Time Code and Cueing document from Feb. 12, 1987 so it has been there from the beginning, just not well documented where you need to see it.
I also had the same problem and I solved it like this:
in logic, join and merge all tracks with all program chances and other controllers in one. When you export the midi file, the duration will be precise.:D
I am also facing the same problem, and i also dont know hot to check its length
i also dont know hot to check its length
What are you using to check its length?