The ramp segments themselves are pretty simple once they get going -- the entire thing is calculated at once, and then it's just a matter of adding the resulting constant increment until the target time has elapsed, or a new event supersedes the current ramp. This is less than the interpolation formula in [tabread4~], and not much more than what [line~] itself has to do (although all the time stuff is done using doubles so there may be some overhead there depending on architecture). But it does have to run one or more nested conditionals every sample. Most of the time it's checking to see if there's something in the linked list, so there isn't much to do, but if you sent it a bunch of events at once, it's got a lot of things it has to do. Here's the per-sample for-loop:
for (i = 0; i < n; i++)
{
double timenext = timenow + msecpersamp;
checknext:
if (s)
{
/* has starttime elapsed? If so update value and increment */
if (s->s_starttime < timenext)
{
if (x->x_targettime <= timenext)
f = x->x_target, inc = 0;
/* if zero-length segment bash output value */
if (s->s_targettime <= s->s_starttime)
{
f = s->s_target;
inc = 0;
}
else
{
double incpermsec = (s->s_target - f)/
(s->s_targettime - s->s_starttime);
f = f + incpermsec * (timenext - s->s_starttime);
inc = incpermsec * msecpersamp;
}
x->x_inc = inc;
x->x_target = s->s_target;
x->x_targettime = s->s_targettime;
x->x_list = s->s_next;
t_freebytes(s, sizeof(*s));
s = x->x_list;
goto checknext;
}
}
if (x->x_targettime <= timenext)
f = x->x_target, inc = x->x_inc = 0, x->x_targettime = 1e20;
*out++ = f;
f = f + inc;
timenow = timenext;
}
-----------------------------------
That's a lot of conditionals. Luckily all of the clock function calls and the can take place outside this loop because sample rate is constant, and the knotty boolean algebra for structuring the event list is handled in the vline_tilde_float method. The goto checknext here adds one extra pass if there are two events scheduled for the same time (I think the vline_tilde_float method ensures that the only way this can happen is in the "leap, then ramp" scenario). Allocating new events (in the vline_tilde_float method) and deallocating past events from the linked list — t_freebytes(s, sizeof(*s)); here — also has some overhead not encountered in [line~].
In general, [vline~] has more to do per event scheduled, and also more to do per sample, than [line~].