\timingOffset doesn't seem to work with \midi


I just noticed that the \midi event type seems to ignore \timingOffset. This is a bit of a disaster for me :smile: as I use \timingOffset a lot and also use hardware synths a lot.

Is there a technical reason for this, for example, does \timingOffset depend on some feature of OSC? Can anyone suggest a workaround? It’s not just a question of playing with \dur, since \dur affects the timing of the next event, not the current one.

It looks like it was never implemented.

I changed 3 lines in Event.sc and it seems to be working.

1 Like

Can you share this?
(lorem impsum dolor klaatu barada nikto my response isn’t long enough)

1 Like

I’m not totally sure how to submit PRs for SC - presumably I need to fork the repo etc.

Replace lines 793 to 815 with the following:

						var freqs, lag, dur, sustain, strum, timingOffset;
						var bndl, midiout, hasGate, midicmd;

						freqs = ~freq = ~detunedFreq.value;

						~amp = ~amp.value;
						~midinote = (freqs.cpsmidi).round(1).asInteger;
						strum = ~strum;
						lag = ~lag;
						timingOffset = ~timingOffset;
						sustain = ~sustain = ~sustain.value;
						midiout = ~midiout.value;
						~uid ?? { ~uid = midiout.uid };  // mainly for sysex cmd
						hasGate = ~hasGate ? true;
						midicmd = ~midicmd;
						bndl = ~midiEventFunctions[midicmd].valueEnvir.asCollection;

						bndl = bndl.asControlInput.flop;

						bndl.do {|msgArgs, i|
							var latency;

							latency = i * strum + lag + timingOffset;

I’m not sure if ~timingOffset here is absolute or relative to the tempo. I’d need to do some playing around to found out.

Thanks for having a look! If you are not comfortable with making a PR, you could open an issue with your findings and include some code that seems to solve the problem. The main thing is that the issue gets reported.

timingOffset is documented at Pattern Guide 08: Event Types and Parameters | SuperCollider 3.12.2 Help

“timingOffset: Number of beats to delay the event’s server message(s).”

Beats are relative to tempo; seconds (\lag) are not.


Thanks. I meant that at the point in the code I was making the change, I wasn’t sure if the adjustment from the user-added value to take account of tempo has already been done or I needed to implement it myself.

If lag is in seconds, then you can’t just add timingOffset in beats.

Following the behavior of the schedBundle functions, the message sends should be scheduled: thisThread.clock.sched(timingOffset, { ... }). Scheduling is the only really correct way because the tempo could change.

What I’m not sure about is whether we support an array for timingOffset or not. If not (if it’s always expected to be a number), then you could schedule the entire do loop. If an array is permitted, then it would be necessary to schedule individual message sends separately.


We do support it in the note event type.

(note: (0..5), timingOffset: (0, 0.1  .. 0.5)).play; // staggered starts

Not exactly related, but on Windows note also that latency key doesn’t work with \midi Events.

I mention this because if you’re using MIDI on Windows and also need to “shift” timing a bit to make hardware devices sync up with the Server, then you need to use a workaround.