|
Post by mms on Apr 3, 2021 11:42:41 GMT
Ureka! I successfully implemented a series of tempo changes in my MIDI sequence. The parser I use, is a little utility I wrote a number of years ago. lt Works pretty good for my purposes. I’ll probably be back with more questions in the coming days. Thank you again.
|
|
|
Post by JohnG on Apr 3, 2021 13:47:36 GMT
So glad you found it useful.
I seem to have found a fault in XGworks version 4.
When one introduces Time Signature changes after the first one, which is created automatically, it fails to insert the correct information about ticks and demsemiquavers. If I then amend the hexadecimal in the last two bytes of the message therafter it does it correctly. Very strange!
It wasn't a fault in Sekaiju.
JohnG.
|
|
|
Post by mms on Apr 3, 2021 20:29:27 GMT
I think XGworks also sets the track length of the music track incorrectly. I see it set at 22 and I believe it should be 262 Strangely, the file plays correctly.
I plan to create a new thread on each of the Set Key Signature and Set Time Signature events.
|
|
|
Post by mms on Apr 4, 2021 5:26:50 GMT
So actually I have some very strange problems with my MIDI sequence.
My sequencer’s playback indicator (that follows the notes as they are played) does not track correctly when I have more than one time signature event. I thought it was a problem with my code, as I had never really addressed the eventuality of more than one tempo in a sequence.
When I play the MIDI file in my sequencer, it shows a midi file with a duration of 26 seconds. This is incorrect. Windows Media Player reports a duration of 44 seconds, which is correct.
Both my sequencer, and Windows Media Player, play the file correctly however.
When I examine the MIDI file with my MIDI parser, the last running time is around 22,800 milliseconds.
I’ve never encountered this discrepancy with any file I’ve created before, but then again, this is my first file with more than one tempo.
Would it be alright if I sent you 2 files to examine? One would be the MIDI sequence, and the other a text file of the parsed MIDI.
Perhaps something will jump out at you.
|
|
|
Post by JohnG on Apr 4, 2021 10:16:01 GMT
Please send the files to my email address, I'll see if I can spot what's going on.
Meanwhile I'm going to try remaking the various things I made for you in SOL2 (also by Yamaha, but later) to see what that creates. Interestingly, when I altered the Hex inside one of the time signatures to correct the number of ticks, subsequent input of time signatures was correct, so some field isn't being initialised somewhere in the code.
JohnG.
|
|
|
Post by mms on Apr 4, 2021 14:27:10 GMT
I've sent the files to your e-mail.
I really appreciate you trying to help me sort this out!
I too thought it might be something with Windows Sequencer not being properly initialized, as I thought I had seen this before, where the sequencer starts off in a state how it was last left.
In this case, I finish the sequence with a tempo of 136 BPM, but start with a tempo of 77 BPM My sequencer reports approx half the time, but plays the proper length.
|
|
|
Post by JohnG on Apr 4, 2021 15:51:26 GMT
Got them.
I'll take a look fairly soon. I'm in the middle of preparing a fairly large sequence at the moment. I'l take a break in a while and try to look at them then.
JohnG.
|
|
|
Post by JohnG on Apr 4, 2021 17:06:57 GMT
This is showing up very strangely in Sekaiju, which is one of the best for displaying the detail in list view.
It shows that you're using SMPTE timing in <division> in the header chunk. It displays that you've got the format set to 24 frames per second and the subframes per frame set to 384, which is quite invalid. And if this is being seen generally then this would account for the timing errors, I'm guessing.
But, looking at the file in hex and your .txt decode it would seem you've got the word set correctly at 01 80(h) = 384 tpqn. You've got bit 15 set to 0 which is correct for MTC not SMPTE. At the moment I'm a bit baffled, it needs further investigation.
JohnG.
|
|
|
Post by mms on Apr 5, 2021 3:37:31 GMT
Thank you so much.
Do Sekaiju, XGworks, and SOL, all report the file as 44 seconds, and play at 44 seconds with the 2 proper tempos?
|
|
|
Post by JohnG on Apr 5, 2021 11:36:27 GMT
Sorry for the long delay, I'm still having a few after effects from having my first CoViD vaccine last week. The lasting one is that it's left me feeling rather weary, but it's going. (I'd rather be vaccinated than not.) SO, having now tried the file in Sekaiju, XGworks v4, SOL2, Cakewalk by Bandlab and Anvil Studio I can report that they all show the length of the file to be around 44 seconds. They all start playing slowly (77 bpm) and noticeably speed up (136 bpm)for the last two measures. And, very strangely indeed, Sekaiju now reports the 384 tpqn correctly, see below. I'm baffled! JohnG.
|
|
|
Post by mms on Apr 5, 2021 13:11:08 GMT
In thinking about this further, what are the units of delta times?
Midi ticks? Not milliseconds? If it is ticks, then my numbers in the square brackets (ie [21500]) are running ticks not running milliseconds.
It has been a long time since I wrote the code to create the MIDI files, and when I am revisiting this now, I might be assuming the wrong thing.
|
|
|
Post by JohnG on Apr 5, 2021 14:26:32 GMT
Yes, delta times are in milliseconds, calculated as per the MIDI 1 SMF spec as follows: (Quotation taken from the MMA MIDI 1 specification.)
"Calculating Delta Times: Now here’s an example of how cumulative delta time gets converted into milliseconds. In the simplest case, there are 2 pieces of information needed: 1) The SMF Header Chunk defines a "division" which is delta ticks per quarter note. (eg., 96 = 96 ppq) (Ref: pg. 4, SMF 1.0) 2) The Tempo setting, which is a non-MIDI data Meta Event typically found at time delta time 0 in the first track of an SMF. If it isn't specified, tempo is assumed to be 120 bpm. Tempo is expressed as microseconds per quarter note. (eg., 500000 = 120 bpm). (Ref: pgs. 5,9, SMF 1.0) To convert delta-time ticks into milliseconds, you simply do a straightforward algebraic calculation: Time (in ms.) = (Number of Ticks) * (Tempo (uS/qn) / Div (ticks/qn)) / 1000 As an example, if the Set Tempo value were 500000 uS per qn, and the Division were 96 ticks per qn, then the amount of time at 6144 Ticks into the SMF would be: Time = 6144 * (500000/96) / 1000 = 32000 milliseconds The above example is a very simple case. In practice, SMFs can contain multiple Set Tempo Meta Events spaced throughout the file, and in order to calculate a correct elapsed time for any Tick, a running calculation needs to be performed. Note that while the Time Signature is not needed to perform the above calculation, Time Signature is needed, however, if the elapsed time is desired for a particular Bar/Beat value. As with Set Tempo changes, the Time Signature can change throughout an SMF, and a running calculation is usually necessary to determine a correct elapsed time for any Bar/Beat."
|
|
|
Post by mms on Apr 5, 2021 16:20:01 GMT
Darn
I thought if delta times were MIDI ticks (and the conversion to milliseconds were done "under the hood"), that would explain why my file was valid, played correctly, and displayed the correct song length in various players.
|
|
|
Post by mms on Apr 9, 2021 12:04:27 GMT
As a test I created 2 MIDI files.
TimeTest_060bpm.mid and TimeTest_120bpm.mid
Both files are identical, and have 60 quarter notes, and PPQN in both is set @ 384, the only difference being the Tempo settings.
In Windows Media Player, the first correctly displays and plays a sequence lasting 60 seconds, the second displays and plays a sequence lasting 30 seconds.
In my midi parser, both files show the last running time as 23,040 (which is 60 QN x 384 PPQN = 23,040)
So it appears that delta times are stored as MIDI "ticks" or "pulses", and the MIDI Spec demonstrates how to convert these "ticks" to seconds.
So I guess I am looking for some affirmation that my understanding is correct, before I go off on a tangent, using misunderstandings to continue on with solving this Tempo issue.
Thanks again for any help.
|
|
|
Post by JohnG on Apr 9, 2021 15:33:58 GMT
Confusing isn't it? And I must admit that I was confused too, but then I've not attempted to write my own sequencing program as you have.
But ... what I decided to do was to duplicate your actions as described above. In order to simplify matters (for me), having created two files with different bpm's, 120 and 60, was to save them as type zero files and then to analyse the hexadecimal.
The result? You're quite correct, within the SMF the delta times are stored as ticks. The part of the MMA document I duplicated was about how to work out the actual time interval between MIDI events, given that the quarter note interval is 500,000 milliseconds at 120 bpm. FF 51 03 07 A1 20 My PPQN was set at 480, I entered three notes, the first a full note, the second a dotted half note, the third a half note, each starting a quarter note after the previous one. The delta time worked out at "83H 60H" apart, regardless of tempo, giving binary 11 110 0000 = 480 ticks.
With the second file at 60bpm tempo works out at 1,000,000 milliseconds per quarter note, this giving the actual delta time between events. FF 51 03 0F 42 40 So each (in this case) note is separated from the next by twice the time interval at 60bpm.
Time (in ms.) = (Number of Ticks) * (Tempo (uS/qn) / Div (ticks/qn)) / 1000. so, 480 * 1,000,000 / 480 /1000 = 1000ms. Or, 1 sec per beat at 60 bpm. (that seems correct!) :-)
The upshot of this is, that a file of 4 x 4/4 measures at 60bpm lasts exactly 16 seconds. Insert a tempo change to 120bpm at the beginning of measure three and it reduces to 12 seconds. i.e. 2 x 4 secs + 2 x 2 secs. And so on.
Maybe we both understand it better now? Perhaps. Phew, what a palaver.
Kind regards, JohnG.
Added later:
The difficulty comes when you have a note that spans a tempo change, i.e. is already sounding before a tempo change and finishes after the tempo change. I.e. the Note On may be at measure 1 beat 1 tick 000 the Note Off at 01:04:480 (at 480tpqn) or similar. The number of ticks will still be 1920 but half of them at 500,000 ms the other half at 1,000,000 ms. I'm not sure how this works with playback software.
|
|