timestampclockmidialsalibalsa

ALSA midi: getting precise timestamps on input


Bonjour,

I'm struggling a little bit with getting as precise as possible timestamps with the ALSA sequencer API.

I have a queue used for enabling timestamping of incoming messages, set-up like this:

snd_seq_port_info_t* pinfo{};
...
snd_seq_port_info_set_timestamping(pinfo, 1);
snd_seq_port_info_set_timestamp_real(pinfo, 1);
snd_seq_port_info_set_timestamp_queue(pinfo, queue_id);

the events I get through snd_midi_event_decode indeed have a timestamp which I can read here:

snd_midi_event_decode(apidata.coder, buffer.data(), apidata.bufferSize, ev);
snd_seq_real_time_t& t = ev->time.time;

but while I can read in the ALSA docs:

The timestamp of the event can either specified in real time or in song ticks. The former means the wallclock time while the latter corresponds to the MIDI ticks. Which format is used is determined by the event flags.

what I actually observe is that the time stamp is roughly from the start of my app / the ALSA port opening, so not the wall clock time.

My question is: how can I get a mapping from this time to an actual wall clock time, e.g. what std::high_resolution_clock::now() would give me for instance. Is there a way to get the origin of the timestamps in real time? Or should I just forego this and use std::chrono::high_resolution_clock::now() and timestamp manually (this gives me a delta between 5 and 30 microseconds to the ALSA seq event timestamp if I set my origin at just after the snd_seq_create_port call but is not a very clean solution -- I really want timestamps as precise as possible, which could even come straight from the hardware depending on the MIDI hardware used)


Solution

  • "Wallclock" is somewhat misleading; you get the current time of the queue, i.e., the time since the queue was started. Through the queue, you can pause or reset this timer. The time is measured either in ticks or in nanoseconds.

    This is based on CLOCK_MONOTONIC, which should be available as std::chrono::steady_clock.