Eventually I got ahold of the Midi Standard 1.0 which helped me solve this riddle for when calculating it myself, and will hopefully help others who have this problem.
When calculating delta time, “Set Tempo” and “Time Signature” meta events need to be handled. Also remember that the raw denominator for “Time Signature” meta events needs to be used as the exponent for raising two to a power:
const float kTimeSignatureDenominator = powf( 2, rawTimeSignatureDenominator );
This first page will cover correctly calculating “Beats Per Minute” (BPM) correctly. And although a lot of examples seem to think you require this to convert delta time ticks to seconds or milliseconds, you don’t.
What is a Beat?
In music, there is something called a Bar, which is a segment of time defined by a given number of beats of a given duration. The values which define a Bar, are called the Time Signature.
A Time Signature, is two numbers, one on top of the other. The numerator describes the number of Beats in a Bar, while the denominator describes of what note value a Beat is.
So 4/4 would be four quarter-notes per Bar, while 4/2 would be four half-notes per Bar, 4/8 would be four eighth-notes per Bar, and 2/4 would be two quarter-notes per Bar.
Now a lot of examples say to default the tempo to 120 BPM, and the time signature to 4/4, which is correct. But when handling the “Set Tempo” meta event, the same examples just use the value straight out to calculate the BPM, which is incorrect if the time signature has changed.
The “Set Tempo” meta event in midi only deals in quarter notes, so if the time signature is 4/8, a quarter-note is not a Beat since its described as an eighth-note, so using it to calculate BPM on its own is incorrect.
const float kOneMinuteInMicroseconds = 60000000; // This is wrong if the time signature is not 4/4 float BPM = kOneMinuteInMicroseconds / newMicrosecondsPerQuarterNote;
So how do we solve this? We use the new time signature to scale our BPM to the correct value.
const float kOneMinuteInMicroseconds = 60000000; const float kTimeSignatureNumerator = 4.0f; // For show only, use the actual time signature numerator const float kTimeSignatureDenominator = 4.0f; // For show only, use the actual time signature denominator // This is correct float BPM = ( kOneMinuteInMicroseconds / newMicrosecondsPerQuarterNote ) * ( kTimeSignatureDenominator / 4.0f );
In the code above, we divide the time signature denominator by four (The number four is the denominator value for quarter note), this gives us the number of notes per quarter note. Four divided by four is one, so the BPM remains the same.
If the value of kTimeSignatureDenominator was “8.0f”, then eight divided by four is two (there are two eighth-notes in a quarter note).
The next page will cover the actual conversion of delta time ticks to seconds (or milliseconds).