At the risk of completely spacing-out most of the people reading this thread (and likely boring others) -- here's some more detail on the two kinds of MIDI APIs we're been talking about. The MM (or MME) API is what most applications probably still use. The DirectMusic API is more recent, has explicit support for timestamps (unlike MM/MME), but is less well supported. The classic ("MM" or "MME") Windows MIDI API A reasonable person, thinking about how MIDI is handled by Windows, would probably assume that Windows associates every MIDI event with a precise instant in time. Obviously, this is necessary in order for MIDI events to be received and then assembled into a coherent musical phrase. It's also necessary in order for a sequence of MIDI events to be transmitted with musically-correct timing relationships. So, a reasonable person might conclude that Windows takes care of this.
A reasonable person -- would be wrong.
The classic Windows API for sending and receiving MIDI events has no notion of time whatsoever. The classic Windows API call for sending MIDI notes is called midiOutShortMsg.
It does not take a timestamp.
Instead - the
application is responsible for calling midiOutShortMsg at "Time A", such that the MIDI data is transmitted from the MIDI DIN jack at "Time B", where 'Time B' is "exactly the right time" within the musical context (e.g. audio channels being played back, other MIDI events, possibly video playback....).
Note that Time A (when the application calls midiOutShortMsg) and Time B (when the MIDI event flies out the DIN jack) are
different times. Lots of low-level processing can occur between Time A and Time B - and usually does. How long does that processing take? That depends, on many factors. Does the processing always take the same amount of wall-clock time? No, because many other processes can temporarily interrupt the low-level MIDI output processing. Things like incoming (or outgoing) audio transfers, network activity (a notorious source of jitter), antivirus scanning, many other things. Can you find out how long the interval between Time A and Time B -- will be? No.
The net result is that the time interval between calling midiOutShortMsg and the actual transmission of a MIDI message is variable, and not controlled by the sequencer application. This directly causes jitter.
Having said that - I'd bet that Sonar uses a kernel-level event scheduler that calls midiOutShortMsg. This means that critical event scheduling, for Sonar, most likely happens at kernel level, at a high priority, to minimize potential jitter caused by other Windows processes. However, if the MIDI device driver is poorly written, jitter will still occur (and Sonar can't do anything about that). If the MIDI device driver is for a USB or Firewire device - then the MIDI data will have to be queued up (again) to go through the USB or Firewire driver stack. Jitter can certainly happen in those driver stacks -- and again, Sonar can't do anything to minimize that kind of jitter. The DirectMusic Windows MIDI API DirectMusic MIDI API associates timestamps with each and every MIDI message.
This is the key difference between DirectMusic MIDI and MME MIDI. DirectMusic timestamps have a nominal resolution of 100 nanoseconds (yes, 0.1 microseconds). That does not mean the actual resolution is that good! If the DirectMusic port is a USB 1.1 MIDI port, all timestamps will be quantized to the 1 millisecond USB frame time. If the DirectMusic port is a Firewire MIDI port, the effective resolution will be something like 0.3 milliseconds (depends on driver implementation). If the DirectMusic port is "emulated' (wrapping a non-DirectMusic MIDI driver).
I like the DirectMusic API, in principle, because
there is a clear path whereby accurate timestamps can be passed all the way from a user-mode sequencer application down to the final low-level MIDI hardware output driver. That doesn't mean the timestamps will always be honored (bad drivers can always be written), but at least it's possible for the timestamp to make it "all the way down".
With the MME API -- there is no way for a timestamp to be passed "all the way down", because the MME API does not handle timestamps at all. As a sequencer developer - I just had to hope that the MIDI events would actually get transmitted "pretty soon" after I called midiOutShortMsg -- and I also had to hope that the "pretty soon" would be the same length of time, , every time. If not -- jitter would occur. And it does.
One more thing. Dewdman42 has asked several times about the clock used by DirectMusic MIDI ports. This is from the DirectMusic (DirectX 9.0) SDK documentation:
To guarantee accurate timing with an acceptably low latency, DirectMusic incorporates a master clock in kernel mode. This clock is based on a hardware timer. DirectMusic automatically selects the system clock as the master clock, but an application can select a different one, such as the wave-out crystal on a sound card.
The master clock is a high-resolution timer that is shared by all processes, devices, and applications that are using DirectMusic. The clock is used to synchronize all audio playback in the system. It is a standard IReferenceClock interface. The IReferenceClock::GetTime method returns the current time as a 64-bit integer (defined as the REFERENCE_TIME type) in increments of 100 nanoseconds.
This hardware timer is
not the same as the 1-millisecond resolution MME timer (although the MME timer is hopefully derived from it!). I believe this hardware timer probably has resolution in the microsecond range, but don't know for sure. Note that since the system hardware timer is not locked to any particular audio sample rate clock, the relationship between audio sample count and system time will drift over time. Therefore, a smart sequencer designer will take steps to periodically reconcile these two timebases (conforming MIDI time to audio time, not the other way around). Alternatively, it might be possible to tell DirectMusic to just directly use the audio sample clock from a particular audio interface .... but not every audio interface driver supports the IReferenceClock interface. If it doesn't - it's impossible to tell DirectMusic to use that audio interface as the master clock.
Here is a quote from 'earthvegaconnection'. This is a guy who has written both MME and DirectMusic replacement drivers for the 8PortSE parallel-port-based MIDI interface. I suspect he know what he's talking about.
Original: http://8portse.earthvegaconnection.com/DM.htm
Non-DirectMusic MIDI devices will appear as emulated MIDI ports to DirectMusic applications. True DirectMusic MIDI devices will appear as both a DirectMusic port as well as an emulated DirectMusic port. The emulated port in this case will be the one that MME applications can use. If you have the choice you should always choose the non-emulated ports. The emulation mode adds about 5 to 7 milliseconds of latency to the MIDI processing.
One of the biggest benefits of DirectMusic drivers is the timestamping of MIDI input. In the Windows MultiMedia system, time related MIDI input data is handled by the receiving application itself. Applications on Windows 2000 and XP always run in so-called user mode. Most of the hardware handling on the other hand, takes place in so-called kernel mode. Kernel mode processing takes priority over processes running in user mode. In practice this means that if another hardware device needs processing time at the time of delivery of the MIDI input, the MME application will just have to wait. Depending on the hardware device in question, the wait time can be considerable.
This results in MIDI input arriving late and, more importantly, variations in the delivery time of MIDI data from hardware to application. This effect is sometimes called MIDI timing jitter. DirectMusic solves this problem by timestamping the input data at the moment of arrival to a system wide reference clock. This timestamping takes place in kernel mode and thus has high priority. The DirectMusic application still runs in user mode but this time, when it receives it's input data, it already has an accurate timestamp.
The result of all this is that DirectMusic applications have more accurate MIDI recording capabilities. They will suffer much less from jitter in timing.