Noticeable latency/delay in playing Pdef

So, I’ve been developing some code for controlling things like synths and patterns with my Akai MPK mini. Today I wrote a simple MIDIdef that listens to noteOn msgs and .plays a Pdef I gave the fn previosly.
The thing is that I’m noticeing (noticing?) some delay between playing a key and the pattern being launched. The delay time variates randomly but goes up to something like half a second, which is really inconvenient. Its not a midi problem since I’ve tried launching a Pdef when evaluating a code block and it produces some similar delay, also the pdef is not quantized in any way.
My laptop is a Lenovo E470, running Antergos -> Gnu/Linux and supercollider 3.10
So, any thoughts/help/suggestion? (I’ve tried lowering the s.latency property with no luck :frowning: )

Hi,

this is an interesting thing I haven’t noticed so far:

(
s.latency = 1;

Pdef(\a, Pbind(\dur, Pn(1, 1))).play
)


// resetting latency, not taken over by Pdef
(
s.latency = 0.05;

Pdef(\a, Pbind(\dur, Pn(1, 1))).play
)

// but taken over by Pbind !

Pbind(\dur, Pn(1, 1)).play


// workaround: clear the Pdef
(
Pdef(\a).clear;

Pbind(\dur, Pn(1, 1)).play
)

I don’t know if this is intended or a bug, Julian would have to say.
I don’t know if he’s around here, I’ll ask on the mailing list.

Pdef.play is quantized to the nearest beat of whatever Clock you’re playing the Pdef on by default (similar to launching clips in Ableton). So if you haven’t specified otherwise, the Pdef will play on TempoClock.default, with its default tempo of one beat per second (60bpm), resulting in a delayed start of up to one second. You can override this behavior for an individual case by calling e.g.

Pdef(\foo).play(quant: 0)

You can change quantization behavior for all Pdefs with class method defaultQuant:

Pdef.defaultQuant_(0)

… or for an individual Pdef like so:

Pdef(\foo).quant_(0)

The documentation for Class Pdef has lots more regarding Pdefs and scheduling. Hope that helps.

OOOhhhh, I didn’t think the default quant was 1, rather than 0. Just tried it and it works! Thanks!
Guess I should’ve dig deeper in the Pdef help file :confused:

1 Like

I did not know either, thanks

1 Like

so, following on this… despite setting default quant to 0 I’ve been having latency when launching patterns using midi messages.
the code is basically this:

var onPad;
onPad = {
	|note pattern clock|

	if(clock.isNil){
		clock = t[0];
	};

	MIDIdef.noteOn(\onPad_++ note ++ pattern,{
		Pdef(pattern).play(clock);
	},note);

	MIDIdef.noteOff(\onPad_++ note ++ pattern,{
		Pdef(pattern).stop;
	},note);
};

and then:


Pdef(\kik_1,
	Pbind(
		\instrument, \kik,
		\dur, 1
	)
);

Pdef(
	\sn_1,
	Pbind(
		\instrument, \simpleSampler,
		\buf, b[\s][0],
		\dur, 1/4,
		\amp, Pseq([
			 \ , \ , \ ,0.8,
			 \ , \ ,0.8, \

		],inf),
		\out, Pwrand([0,~delayBus],[0.7,0.3],inf)

	)
);


//t is an array of two TempoClocks.
//m is a dict containing several fns for working with midi.
m[\onPad].(0,\kik_1, t[0]);
m[\onPad].(1,\sn_1,  t[0]);



So, the latency is noticiable if I try to launch a pattern, wait a little bit and the launch another in sync. I’m a drummer, so it is specially frustrating this kind of subtle but noticiable latency. I’ve come to the conclusion that since sclang is handling midi, I think, I cannot make things run faster. But maybe there is something that I’m missing…

Latency is independant from quantization. With setting quant you play on a grid, latency is the server latency which is necessary to ensure exact timing with language-based sequencing, see:

http://doc.sccode.org/Guides/ServerTiming.html

You need quantization on a grid mainly to sync different patterns. You can reduce server latency to 0.05 or so, maybe a bit less (default 0.2), but 0 makes no sense if you want exact rhythms. If even low latency is unacceptabe for your use case, consider server-based timing with demand ugens.

Did you consider that latency setting with Pdef doesn’t work under circumstances that I described above ?

Yeah, not a drummer but I definitely sympathize.

Are you able to achieve what you consider acceptable timing with the same MIDI controller, MIDI interface, and computer using different software?

If not, SC may not be the issue. MIDI timing is anything but straightforward, particularly over USB.

If MIDI is the source of the latency problem or not, can be checked by using SC’s MIDI spoof methods.

http://doc.sccode.org/Classes/MIDIFunc.html#examples

Thanks! Will try that ASAP

Well, I’ve been using bitwig studio for a while, where I mostly use arpeggiators and a set of modulators before drum samples and synths to build proto beats (https://www.youtube.com/watch?v=NoDd8V5jKnk, as reference); and I never suffered any latency. In a way, I’m trying to replace this logic of arps with patterns as SUPERCHARGED arpeggiators.
I hope I find a solution to this, seeing that Bitwig is a monster of a software, with all the whistles and bells, is shame that I’m having this issue in SC. I really hope that I’m being negligent (again) in some way…

Reading more into this, I realize i don’t know how to really test it.

I’ve run manually using Shift + Enter

MIDIIn.doNoteOnAction(num:0);

and I notice latency between my keyDown and the pattern starting.
After that I’ve tried spoffing a second note to launch another pattern manually, trying to sync it to the first one. If a keyDown on tempo it starts slightly offseted, which “proves” there is some latency (but using the notebook keyboard to try time intensive events is not the best way.
If I spoofs both notes in the same block of code

(
MIDIIn.doNoteOnAction(num:0);
MIDIIn.doNoteOnAction(num:1);
)

they start in sync, which doesn’t say anything

lastly, I tried running a task that spoofs the first note/pattern, waits 1 second (giving that the tempo clock is set to 1 for this example) and then spoofs the second one. They start in sync …

(
Task({
	MIDIIn.doNoteOnAction(num:0);
	1.wait;
	MIDIIn.doNoteOnAction(num:1);
}).start;

)

Well, for the moment I found that the best way is to set the latency of the server to a really low value (atm 0.03). There is still some tiiiny annoyance but it may as well be my human playing imprecision.
I’m getting a bunch of “late” messages in the post window that I assume is scynth telling me that is not being able to process at the speed I’m asking. Is there any “danger” in this messages? Am I going to have a bunch of xruns or things like that in the future because of this setting??

Thanks for all the help!!

Sorry to be late to this, only just found this forum.

Yeah, that’s pretty much what you have to do.

dkmayer already mentioned Scheduling and Server timing | SuperCollider 3.12.2 Help – if you’re just running patterns in SC and don’t need to sync to anything else, you don’t have to worry about it too much, BUT if you need something more specific, and it’s very important to understand the concepts in that help file.

Most MIDI gear/software sends messages with the expectation that the receiver will do it Right Now.

SC splits the language and audio server into separate applications that communicate over the network – which creates some exciting possibilities that most other software doesn’t have, but… it takes time for sclang’s messages to go to the server. So, necessarily, sclang has to do its work slightly earlier than you hear the result. That’s inherently incompatible with MIDI’s expectation. All you can do is reduce the damage.

I don’t know Bitwig’s internals, but it doesn’t have to deal with the network in the same way.

“late” only means that the message was timestamped to happen at time x, but it arrived at the server at time y, and y is later than x – so it was impossible for the server to do it “on time.” It has nothing to do with CPU load. xruns are a totally different thing, completely not related.

In my live performances, I got better results by setting up patterns to start and stop on barlines, and hitting the trigger before the barline.

hjh