lua: get wall clock time

Hello

Would it be possible, in lua DSP plugins, to get access to the wall clock time?
I know you can get the current playhead position, but it could be useful to know ‘when’ we are.
That would enable to compute MIDI jitter, for instance by comparing or graphing the current time, when receiving MIDI events.

Thank you

You will not be able to compute MIDI jitter in this way.

If I loop a region with midi notes, and that I graph the time of each MIDI not received, I will be able to see if the clock of my MIDI device is stable, don’t you think?

i don’t know what you’re thinking, but i don’t think that you’re thinking the right thing. MIDI “clocking” is not really related to any of this stuff, adn the extent to which it is (i.e. the serial clock) really no relationship to MIDI jitter.

A plugin can run at any given time in the current process cycle. A relation to wall-clock in the plugin makes no sense.
MIDI events are timestamped (relative to the beginning of the process cycle). Jitter inside the process cycle is by design and definition zero.

To measure hardware MIDI i/o jitter, you’ll have to use a dedicated tool. Even Ardour’s main process-callback is not aligned to wall-clock. MIDI events are timestamped at lower level.

To elaborate: Say you use a buffer of 1024 sample/period at 48KHz. A process cycle is 21.3ms long.

Now the soundcard fires an IRQ at 11am and delivers 1024 audio-samples from 10:59:59:979 to 11:00:00:000 and corresponding MIDI events, say an note-on event at 10:59:59:990
That MIDI event will get a timestamp 528 [samples into the cycle] ((990 - 979) * 1000[ms] / 48000).

The IRQ eventually wakes up jackd, and jackd will call all jack-clients in turn and at some point wake up Ardour, which in turn processes all tracks & busses. All of this is subject to operating-system scheduling: semi-random and maybe even in parallel on different CPU cores (as long as the process-order is a valid solution to the process-graph).

At some point a synth plugin in Ardour will run, process the note-on and synthesize audio into the output buffer: zeros until sample 527 and sound after sample 528 until the end of the cycle 1023.
The synth’s DSP can run at any given time between 11:00:00:000 or at 11:00:00:021 it won’t make a difference.

As long as everything completes before wall-clock time 11:00:00:021 (next soundcard IRQ) all is fine. The sound will be written back, perfectly in sync with 1 cycle delay (*).

The problem with MIDI jitter is at a lower level, most soundcards use separate IRQs for audio and MIDI (Firewire is the sole exception that per spec mandates MIDI to be in the same datastream, timestamped. USB devices are the worst because those requires separate IRQs and MIDI appears as separate device. For PCI[e] soundcards there’s no definite spec: It’s left to the vendor). The jitter for MIDI happens at driver and audio-engine level: associating MIDI event-time with the audio-cycle during capture and playback (hardware i/o)

(*) reality is a bit more complicated, There are usually 2 periods latency input+output buffers or in async-mode 2 output buffers, but still: zero jitter.

Thank you for your explainations x42.
Seems I used the ‘jitter’ term incorrectly.
I’d like to send MIDI notes from an external device to Ardour, and measure if the MIDI events occur at the right time, and if the external clock is stable (I’m not talking about the MIDI clock).
I have experienced cases where the MIDI notes come too early or too late, for instance.
Let’s say I play a loop where I send 1 MIDI event per second. I would expect them to be regularly separated by 1s.
I thought it could be doable with a lua DSP plug in, by printing the time on each MIDI note received.

For the case at hand: Ardour’s MIDI-tracer (Menu > Window > MIDI tracer) with delta times would be an easy way to check.

You really want to compare it to the audio-clock (not wall-clock). Count audio-samples: You can do that in a DSP plugin. In your example there should be “sample-rate” amount of audio-samples between the two MIDI events.

Anyway, I’ll add a lua-binding to expose g_get_monotonic_time() that might come in handy regardless (e.g. profiling inside the same callback – Also note that wall-clock is also not linear/monotonic: NTP may correct it, it can jump due to daylight-savings, leap-seconds,…) Lua’s built-in OS libary (time, timezone etc) provides no guarantees about realtime safety and is hence not available for DSP scripts.

Still for the case at hand, it is not a correct measurement to correlate system time of when process() is scheduled between different process callbacks. As explained above if you measure times between two process callbacks of the same plugins inside the plugin, they can jitter on the order of the period-size.

Thank you for this addition. x42. And thank you for these advices. I will use the number of audio samples to compare several midi events.

You say that process() calls can jitter. Is it also the case for live MIDI events, coming from a MIDI interface?

Is it relevant to compare a number of ’ elapsed’ samples, to the playhead position, in samples?

There’s usually jitter on MIDI data for the case: MIDI-cable -> soundcard -> buffer -> IRQ -> operating-system -> IRQ-handler -> driver add timestamp to event.

Also note that a MIDI-event is rather long, at least in case of analog physical MIDI: 31.25 kbaud. a 3 byte note-on/off message spans about 1ms.

There’s https://github.com/x42/jack_midi_latency which can produce plots like http://gareus.org/wiki/midilatency to quantify latency and jitter