Cabbage Logo
Back to Cabbage Site

Host TIME_IN_SECONDS modulo 1 unexpected behaviour

I’m trying to synk an instrument to the host beats. Given that the host info doesn’t provide beats and phase info I was trying to use the modulo operator to “capture” the beats, but apparently this isn’t a solution…

instr 1
	kIsPlaying chnget “IS_PLAYING”
	kTimeInSeconds chnget “TIME_IN_SECONDS”

	if kIsPlaying==1 then
		if (kTimeInSeconds % 1)==0 then
		  printk 1, kTimeInSeconds
		endif
	endif
endin

This code prints only each 4 seconds. The same if I do modulo 2 or modulo 4.
With module 3 it prints every 12 seconds.

image

I guess that using a modulo condition on a control rate variable is not reliable. Who guarantees that the control rate kicks exactly at the right time? By the way I don’t understand why it happens a multiples of 4…

I’ve tried to see if something changes if I set different sampling rates, but it seems it doesn’t have any effect.

Perhaps you should try HOST_PPQ_POS instead? Technically, if you want these to be sample accurate you will need to run with ksmps=1. Alternatively you could just use a combination of IS_PLAYING and HOST_BPM to work out your own beats :thinking:

If I’m not wrong HOST_PPQ_POS is obtained from AudioPlayHead::CurrentPositionInfo::ppqPositionOfLastBarStart which is not provided by some hosts. Isn’t it?

Ugin BPM is not enough becuase I’m programming a MIDI instrument that needs to be synced and aligned to the host bars and beats…

I think ProTools only, but I could be wrong…? Did you try it?

Reaper crashes if I define kPPQPosition chnget "HOST_PPQ_POS"

Hmm, that answers that question then. Let me run it through the debugger…

Works fine here?

I’m on Windows. Are you running OSX? I can try there later…

Actually it was some problem with the compiled VSTi.
Now it works. I’ve tried another trick, and now I can sync with bars correctly

ksmps = 1
nchnls = 2
0dbfs = 1

kIsPlaying chnget "IS_PLAYING";
kPPQPosition chnget "HOST_PPQ_POS";
kTimeSigNum  chnget "TIME_SIG_NUM";
kTimeSigDenom chnget "TIME_SIG_DENOM";
kquarterNotesPerBar = kTimeSigNum *4 / kTimeSigDenom;
klastBarPos = int(kPPQPosition/kquarterNotesPerBar)*kquarterNotesPerBar;


if kIsPlaying==1 && changed:k(klastBarPos)==1 then
	printk 1, klastBarPos;
endif

Do you think there’s a better solution? I’m a bit worried by ksmps = 1

You can run a UDO with ksmps set to 1, while the rest of the orc runs at something higher? Might help some?

Right! UDO is the way to go. Thanks @rorywalsh :wink: