inaccurate timing of a metro synced to Live's transport

Adrian Gierakowski's icon

Hi,

I've been working on a step sequencer in max4live and noticed that the output of a metro synced to Live's transport is quite inaccurate. Midi note triggered by the metro are delayed by a number of samples (10-20) compared to midi notes coming from a Live clip. I could live with it if the delay was constant but, there is aslo a substantial jitter.

I though that metro synced to Live's transport was supposed to be "tick accurate".

This kind of jitter makes max4live kind of useless for designing step sequencers, since it introduces random phasing problems

I've attached a max4live patch as well as an audio file demonstrating the issue. In the audio file, I have recorded outputs from two instances of Impulse. One driven by a midi clip the other by a metro synced to the beat. Both instances trigger a sample with an impulse. In the audio file (if you zoom in) you can see that the impulse with higher amplitude (which was triggered by metro) is delayed by a "random" number of samples in relation to the other impulse (which always happens exactly on the beat).

Has anyone encountered a similar problem?

I'd really appreciate some comments from the devs on this one.

best

Max Patch
Copy patch and select New From Clipboard in Max.

Adrian
btw. I'm running Max 6.0.5 and Live 8.3
patch used to trigger the notes below:

4789.00062Audio.aif
aif
broc's icon

"I think that 1ms is about the resolution of the Max event world"

Qoute from this thread (Chris Muir).

Adrian Gierakowski's icon

Hi broc,

yes, I know there are limits to the timing resolution of messages in Max (but only as interpreted by MSP objects: evens in the scheduler are actually time stamped with 64bit accuracy) and it is linked to the signal vector size (if overdrive is on), but I though that there was some mechanism built into the transport system, which would make things tightly synced with Live's midi timing (so accuracy down to 1 tick).

anyway, this discovery sucks!

best

pid's icon

yeah you have discovered the limitations of m4l / live.

there are a few things going on, such as the always on delay incurred going in and out of an m4l device that is also cumulative, the fact that live's pdc does not compensate, the fact that in live, max is fixed overdrive on, audio in interupt on, sig vector 64.

i'm not sure that this is fixed in 9 / 6.1 either. probably still a project for the devs for the future. quite a huge impossible task though i imagine. only concept of a shared audio graph would fix? i do not know entirely what i am talking about but that is the impression i get. it has always been that way.

broc's icon

> yeah you have discovered the limitations of m4l / live.

But the limits of event timing resolution are imposed by max, not m4l / live.
(for example, supercollider provides event resolution in microseconds).

Adrian Gierakowski's icon

@pid
a question that coms to mind: is this information stated anywhere in the docs?

@broc
this is a limitation of most real time sound processing softwares. Some exceptions are for example Chuck~ and LuaAV (they are "strongly timed"). I haven't used supercollider that much but I believe it also suffers from the it. The problem is not the actual timing of messages, but at what time intervals these messages can affect the audio graph. But still, there are workarounds. Like delaying everything by a vector and making the audio objects aware of the time stamps (which can be as accurate as the clock of the cpu) of the messages. This solution is used in gbr.ola~ from IRCAMs FTMGabor packed, or in vline~ in PD). By the way, I am wondering why nobody has programmed a vline~ like external for Max yet (question to devs: is it even possible?).

So my point is: I thought that developers have come up with some workaround for messages synchronised to transport. Wishful thinking :)

Venetian's icon

@broc: “1ms is about the resolution of the Max event world… the limits of event timing resolution are imposed by max, not m4l / live.”

I don't think this is correct. It’s true that in Max standalone, the Max thread operates at 1 msec intervals. However, I’ve started to investigate the timing accuracy in Max for Live and in Max standalone and it seems that in M4L, the timing accuracy depends on Live’s buffer size and the 1 msec scheduler is no longer used (rather the updates happen every audio buffer). I’ll explain my thinking here.

Firstly, I’ve looked into the issue to simply receive a bang every beat and timestamp this. At 120BPM, in M4L you get jitter at +- 0.6ms, ~20-30 samples. This is related to the buffersize of Live. It doesn’t make any difference if you do a system time call each beat message or calculate via sample index, this jitter is present. With my buffer size in Live set to 64, every 64samples, the Max device will look at the Max objects and update the Max thread updates based on logical timestamps: i.e. replacing the regular 1msec callbacks on messages of the max, as opposed to MSP, world, with callbacks every 64samples, i.e. 1.4 msec.

For this metronome test, if you increase the buffersize of Live to 256, I find a regular sequence of intervals to be roughly:
499.2, 499.2, 499.2, 499.2, 499.2, 499.2, 504.6, 499.2, etc
i.e. jitter is ~ 0.8msec about 8 times, then +4.6 msec.

The reason is that the the bang will occur at the end of the audio buffer during which the event was scheduled. So when the buffer size is 256, an interval of 500msec is 86.13 buffers. The interval reported will most often 86 buffers (499.23 msec) and occasionally 87 buffers (505.03 msec).

This agrees with the idea that the message update routine is called after the audio update routine in Live. So.... definitely a problem if you want accurate synchronisation with Live's beats.

In Max standalone, the same calculation reveals a jitter of up to 50 microseconds.

Using the cpp function thisthread.getid(), I've compared the thread of the bang message from the metronome with the audio thread, and it's the same thread - so essentially, it's looking likely that for my MSP~ object, any messages will be picked up when the audio callback gets called. I've used both the std::chrono::high_resolution_timer (C++ standard library within an external) and the Max object [cputime] to check the intervals between a regular metronome running in Max for Live. With both methods, the jitter depends on buffer size, going up to 4msec with a 256 buffer, and is less for a 64 sample buffer +- 1msec.

Interestingly, if you use the timer object in Max, there is no reported jitter, even in M4L, suggesting that Max has logical timestamps that are idealised and these are used to schedule Max events. When comparing events, the logical timestamps are used, so the reported interval is 500 each bang, regardless of what the actual interval was.

Valiumdupeuple's icon

Thanks, this is really interesting Venetian. Theoretically... and philosophically.
Did we became so accustomed to straight machines beats so that we can't live with a 10 samples inaccuracy? Well, analog drum machines aren't that precise. Ok, so, does this M4L "problem" makes Live sounding analog? :-) Would everyone search for this inaccuracy in 20 years?

Sorry to chime in this way. I'm actually really concerned by this issues, so thx again Venetian for this investigation. Let's hope that it gets better in the near future.