Midi Delta Time Ticks to Seconds
Converting Delta Time
In some documentation of the midi file format, people have wrote that there are two types of time divisions: “Ticks Per Beat” and “Frames Per Second”. However as mentioned in the previous page, this is a misclassification if the Time Signature is not 4/4, it should read “Ticks Per Quarter-note”.
So hopefully, your first midi events you parsed before getting a delta time greater than 0 were “Set Tempo” and “Time Signature” meta events. If not, default your Microseconds Per Quarter-Note to 500000 and your Time Signature to 4/4.
We won’t actually be using the Time Signature in this calculation, but it is required if you want the length of a Bar. Also it is better to store the Microseconds Per Quarter-Note value from the “Set Tempo” meta event, rather than using it to calculate the BPM.
Okay so we have the length in microseconds for a quarter-note, and we know there are 1000000 microseconds in a second so to get the length of a quarter note in second:
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f;
Delta times are stored as ticks, so what we need to know now is how many ticks make up a quarter-note. And in the header of the midi, we have the time division “Ticks Per Quarter Note”.
We can divide our kSecondsPerQuarterNote by “Ticks Per Quarter Note” to give us “Seconds Per Tick”, so when we multiply by our delta time seconds, we get the proportion of time our ticks make up of a quarter-note.
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f; const float kSecondsPerTick = kSecondsPerQuarterNote / m_midi.Header.ticksPerQuarterNote; float deltaTimeInSeconds = midiEvent.deltaTime * kSecondsPerTick.
And through cross multiplication, we can reduce this code down to a single division and a two multiply instructions.
const float kSecondsPerTick = midiEvent.deltaTime / (m_midi.Header.ticksPerQuarterNote * 1000000.0f ); float deltaTimeInSeconds = midiEvent.deltaTime * kSecondsPerTick;
Remember that delta times are cumulative, and the next event’s delta time needs to be added onto this one after it has been calculated. If you want the time in milliseconds, just exchange 1000000.0f for 1000.0f, which is the number of microseconds in a millisecond.
DO NOT just add up the unconverted delta time ticks, since Time Signature and Set Tempo events can change the meaning of these numbers partway through a midi track.
And finally, how to calculate the length of a Bar.
Calculating a Bar Length
Using the above code, we calculate the number of seconds per quarter-note.
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f;
Now our Time Signature may not have quarter-notes as the note value for a Beat, so we need to use the Time Signature denominator to scale. Since these are prone to change within a midi track, iterate through your midi events calculating changes until you reach the point in time you want the Bar length for.
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f; const float kTimeSignatureNumerator = 4.0f; // For show only, use the actual time signature numerator const float kTimeSignatureDenominator = 8.0f; // For show only, use the actual time signature denominator const float kSecondsPerBeat = kSecondsPerQuarterNote / ( kTimeSignatureDenominator / 4.0f );
In the above example, our Beat is eighth-notes, so we find out how many eighth-notes are in a quarter note (which is two), and divide by that number to get the length of our Beat in seconds.
Now we just need to multiply by the Time Signature numerator to scale our Beat length by the number of Beats in a Bar.
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f; const float kTimeSignatureNumerator = 4.0f; // For show only, use the actual time signature numerator const float kTimeSignatureDenominator = 8.0f; // For show only, use the actual time signature denominator const float kSecondsPerBeat = kSecondsPerQuarterNote / ( kTimeSignatureDenominator / 4.0f ); float kBarLength = kSecondsPerBeat * kTimeSignatureNumerator;
Using cross-multiplication we can simplify this further
const float kSecondsPerQuarterNote = m_microsecondsPerQuarterNote / 1000000.0f; const float kTimeSignatureNumerator = 4.0f; // For show only, use the actual time signature numerator const float kTimeSignatureDenominator = 8.0f; // For show only, use the actual time signature denominator float kBarLength= ( kTimeSignatureNumerator * kSecondsPerQuarterNote * 4.0f ) / kTimeSignatureDenominator;
Hopefully this has given you a better understanding of midi delta times, and even got your code working now no matter what the Time Signature.
[Previous Page...]No Comments »
RSS feed for comments on this post. TrackBack URL
Leave a comment
You must be logged in to post a comment.