Trigger ugens handling of "frac"

In the source code of UGens accepting triggers I can see that there is some fractional handling of time/phase going on which I don’t yet understand. For instance in Phasor_next_aa these lines are used when a trigger occurs, where previn is the last trigger sample, curin the current one, zrate the current rate, and level the output sample.

if (previn <= 0.f && curin > 0.f) {
   float frac = 1.f - previn / (curin - previn);
   level = resetPos + frac * zrate;
}

Can somebody please explain what the logic of this construction is and when it is used and useful? Unfortunately I could not find it documented or mentioned anywhere so far.

It looks like it calculates a fractional value above the reset value equivalent to one step of the phasor:

({
	var dust = Dust.ar(20);
	var phasor = Phasor.ar(dust, Rand(10,50)/SampleRate.ir);
	
	Latch.ar(phasor, dust).poll;
	nil
}.play)

I think the answer to your question is likely that it is the most efficient way to do this, but like much of the original source, it is abstruse to say the least.

Sam

I found this strategy used in the UGens ZeroCrossing, Timer, Sweep and Phasor. Looking at ZeroCrossing shows that there it is used to compute the zero crossing between two samples through linear interpolation. It also keeps the last fraction when it computers the time interval between the current and the last crossing (assuming that counter was already incremented when the crossing is detected in the if statement). This is also documented in the help file.

if (counter > 4 && previn <= 0.f && curin > 0.f) {
   float frac = -previn / (curin - previn);
   level = unit->mRate->mSampleRate / (frac + counter - prevfrac);
   prevfrac = frac;
   counter = 0;
}

So there it now make sense to me, as it does in Timer, which computes the same output, with the only difference that ZeroCrossing ignores times smaller than 5 samples. With this perspective, maybe the trigger inputs to Sweep and Phasor are also meant to take into account the time of the zero crossing to start their ramps but offsetting the phase.