Great stuff
However, keep in mind that not everyone is familiar with MIDI files timings in general, so I'll post a link to a page with the complete documentation:
http://segaretro.org/MIDI
For reference, this is the WriteVgmWait subroutine from my YM2612 midi2vgm converter, which obviously only works with non-SMPTE timing:
Code: Select all
Private Sub WriteVgmWait()
Dim tmp As Long
Dim tmp2 As Byte
VgmWait& = ((midiWait& * (Tempo& / 1000000)) * 44100) / TimeDivision
TotalVgmWait = TotalVgmWait + VgmWait&
tmp = VgmWait& \ 65535
For tmp2 = 1 To tmp
vgmData$ = vgmData$ + Chr$(&H61) + String$(2, 255)
Next tmp2
tmp = VgmWait& Mod 65535
Select Case tmp
Case Is = 0
Case Is < 17
vgmData$ = vgmData$ + Chr$(&H6F + tmp)
Case Is = 735
vgmData$ = vgmData$ + Chr$(&H62)
Case Is = 882
vgmData$ = vgmData$ + Chr$(&H63)
Case Else
vgmData$ = vgmData$ + Chr$(&H61) + Chr$(tmp And 255) + Chr$(tmp \ 256)
End Select
midiWait& = 0
End Sub
In this code, the TimeDivision variable is that value taken from the header when you're not using SMPTE, and it tells how many ticks there are in a quarter note (a typical value is 480, for example), and the Tempo& variable is read from the MIDI data (meta event $51), it defaults to 500000, and it's measured in microseconds per quarter note. The midiWait variable is incremented by reading the delta times between notes and events, and it's obviously reseted to 0 once the Vgm Wait has been written into the file. It is technically possible for a MIDI to have two events which happen faster than the VGM resolution (1/44100th of a second); in that case, you're fucked. Fortunately it's not a common case.
Note that the code above is probably obsolete by now, as I gave the complete source code of my YM2612 midi2vgm converter to ValleyBell, who's been improving it
a lot. However, this works, and it can be a starting point for other people