MIDISyncClock error

When i use MIDISyncClock , below error occurred.
Is this bug or i made wrong something?

Pdef(\pdef_tes1).play(MIDISyncClock , quant: -1);

ERROR: binary operator ‘-’ failed.
RECEIVER:
nil
ARGS:
Float 2776.970213 BFC57D4D 40A5B1F0
nil

PROTECTED CALL STACK:
Meta_MethodError:new 0000023466E39D00
arg this = BinaryOpFailureError
arg what = nil
arg receiver = nil
Meta_DoesNotUnderstandError:new 0000023466E3BCC0
arg this = BinaryOpFailureError
arg receiver = nil
arg selector = -
arg args = [ 2776.9702131, nil ]
Object:performBinaryOpOnSomething 00000234669161C0
arg this = nil
arg aSelector = -
arg thing = 2776.9702131
arg adverb = nil
Meta_MIDISyncClock:seconds 0000023466F144C0
arg this = MIDISyncClock
a FunctionDef 0000023466F0EB80
sourceCode = “”
Function:prTry 000002346710FA40
arg this = a Function
var result = nil
var thread = a Thread
var next = nil
var wasInProtectedFunc = false

CALL STACK:
DoesNotUnderstandError:reportError
arg this =
Nil:handleError
arg this = nil
arg error =
Thread:handleError
arg this =
arg error =
Object:throw
arg this =
Function:protect
arg this =
arg handler =
var result =
< FunctionDef in Method Meta_MIDISyncClock:initClass >
arg data = 0
var lastTickDelta = 0.0250060999997
var lastQueueTime = 90432.0
var nextTime = 2776.9701929
var task =
var tickIndex = nil
var saveClock =
Meta_MIDISyncClock:tick
arg this =
arg index = 8
arg data = 0
Meta_MIDIIn:doSysrtAction
arg this =
arg src = 0
arg index = 8
arg val = 0
^^ The preceding error dump is for ERROR: binary operator ‘-’ failed.
RECEIVER: nil

Currently MIDISyncClock expects the clock source to begin by sending a start message before the ticks.

Maybe it’s only sending tick messages?

The help file describes the recommended procedure to start the clock – it’s a bit delicate. Try that procedure first.

If there’s no way to make the source send a start message, I might be able to change the class – but IMO that’s a bit risky. Clock messages have no data – so the only way to be sure the SC receiving clock is in sync with the source’s barlines is to receive a distinct message (“start”) at the beginning. You should not just connect MIDISyncClock to an already running clock because you have no idea where the beat is.

hjh

For a sanity check, I hacked up a MIDI clock source in Pure Data[1] and the following procedure “works,” more or less.

  1. Open Pd. Make sure it has a MIDI out port (in Linux, make sure it’s ALSA and not OSS MIDI).

  2. Open the clock patch, but don’t start it yet.

  3. In SC:

    MIDIClient.init;
    
    MIDIIn.connect(0, MIDIClient.sources.detect { |src| src.device.contains("Pure Data") }.uid);
    
    MIDISyncClock.init;
    
  4. Only after initializing MIDISyncClock, then click the toggle in the Pd patch.

  5. Then in SC:

    s.boot;
    s.latency = nil;
    
    p = Pbind(
    	\degree, Pn(Pseries(0, 1, 8), inf),
    	\dur, 0.5,
    	\amp, 0.1
    ).play(MIDISyncClock, quant: -1);
    

At this point, it plays sort of in time with the Pd metronome. But, I hear a little “swing.” I think this is because 1/ MIDI message timing may not be exact and 2/ SC is reacting to incoming MIDI, so it’s always a bit behind (and setting nil latency, to get “as soon as possible” response, sacrifices the timing precision that SC gains from sending timestamped messages).

The sync is not bad in this demo, but I think this is partly because both SC and Pd are subject to the same audio driver latency. If you’re using a hardware MIDI clock source, the hardware will have essentially zero latency, while SC will have 5-50 ms latency depending on the hardware buffer size. Getting SC to sound precisely in time with the hardware is probably impossible (though, if you can afford to reduce the hardware buffer size, it might be somewhat acceptable).

^^ That’s an important point. I think sometimes people discover MIDISyncClock and then develop the expectation that near-perfect sync should be relatively straightforward. You should not have this expectation, at all. It simply doesn’t ever work that well.

If, as I suggested in the other thread, you use SC as the clock source, then you can set the latency for outgoing MIDI to match server messaging latency. The result will probably be better in that case.

If (also as suggested in the other thread) you have the option to use Ableton Link (in SC, LinkClock), latency compensation is built into it and results are likely to be better than MIDI can possibly achieve.

hjh

[1]

I’m using this midiclock device.
It could send “start” .And i check it with openframeworks.
https://www.e-rm.de/midiclock/

I tried sending “start” message after below comand.

MIDIClient.init; //setp1
MIDIIn.connectAll; //step2
MIDISyncClock.init; //step3

But interpreter crashed.
Interpreter has crashed or stopped forcefully. [Exit code: -1073741819]

I tried send “start” message after step2 , also interpreter crashed.
Is there any setting??

“continue” and “stop” message dose not make this problem.