<div dir="ltr"><div class="gmail_default" style="font-family:verdana,sans-serif">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:<br></div><div class="gmail_default" style="font-family:verdana,sans-serif"><br></div><div class="gmail_default" style="font-family:verdana,sans-serif">--------------------------------------------</div><div class="gmail_default" style="font-family:verdana,sans-serif"><div class="gmail_default">    for (i = 0; i < n; i++)</div><div class="gmail_default">    {</div><div class="gmail_default">        double timenext = timenow + msecpersamp;</div><div class="gmail_default">    checknext:</div><div class="gmail_default">        if (s)</div><div class="gmail_default">        {</div><div class="gmail_default">            /* has starttime elapsed?  If so update value and increment */</div><div class="gmail_default">            if (s->s_starttime < timenext)</div><div class="gmail_default">            {</div><div class="gmail_default">                if (x->x_targettime <= timenext)</div><div class="gmail_default">                    f = x->x_target, inc = 0;</div><div class="gmail_default">                    /* if zero-length segment bash output value */</div><div class="gmail_default">                if (s->s_targettime <= s->s_starttime)</div><div class="gmail_default">                {</div><div class="gmail_default">                    f = s->s_target;</div><div class="gmail_default">                    inc = 0;</div><div class="gmail_default">                }</div><div class="gmail_default">                else</div><div class="gmail_default">                {</div><div class="gmail_default">                    double incpermsec = (s->s_target - f)/</div><div class="gmail_default">                        (s->s_targettime - s->s_starttime);</div><div class="gmail_default">                    f = f + incpermsec * (timenext - s->s_starttime);</div><div class="gmail_default">                    inc = incpermsec * msecpersamp;</div><div class="gmail_default">                }</div><div class="gmail_default">                x->x_inc = inc;</div><div class="gmail_default">                x->x_target = s->s_target;</div><div class="gmail_default">                x->x_targettime = s->s_targettime;</div><div class="gmail_default">                x->x_list = s->s_next;</div><div class="gmail_default">                t_freebytes(s, sizeof(*s));</div><div class="gmail_default">                s = x->x_list;</div><div class="gmail_default">                goto checknext;</div><div class="gmail_default">            }</div><div class="gmail_default">        }</div><div class="gmail_default">        if (x->x_targettime <= timenext)</div><div class="gmail_default">            f = x->x_target, inc = x->x_inc = 0, x->x_targettime = 1e20;</div><div class="gmail_default">        *out++ = f;</div><div class="gmail_default">        f = f + inc;</div><div class="gmail_default">        timenow = timenext;</div><div class="gmail_default">    }</div><div class="gmail_default">-----------------------------------</div><div class="gmail_default"><br></div><div class="gmail_default">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 <i>goto checknext </i>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~].</div><div class="gmail_default"><br></div><div class="gmail_default">In general, [vline~] has more to do per event scheduled, and also more to do per sample, than [line~].</div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Sep 27, 2015 at 1:03 AM, Jonathan Wilkes <span dir="ltr"><<a href="mailto:jancsika@yahoo.com" target="_blank">jancsika@yahoo.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div style="color:#000;background-color:#fff;font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px"><div><div><div style="color:#000;background-color:#fff;font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px"><span class="">> And what vline does, is it reads that list, and then schedules itself to
 be hit after the correct amount of logical time has elapsed.<br clear="none"><div><br clear="none"><span></span></div></span><div><div><span>I'm not exactly sure what "schedules itself" means here.  So I'll just</span></div><div dir="ltr"><span>start explaining how it works until I understand it myself... :)<br></span></div><div><span><br></span></div><div><span>The [vline~]</span></div></div><div dir="ltr"><div dir="ltr"><span>object processes blocks of samples at a time (in vline_tilde_perform)</span><span>.  But</span></div><div dir="ltr"><span>any of those clock events Frank mentioned that happen to be "ripe" for</span></div><div dir="ltr"><span>the upcoming block get sent to the "float" method of line (vline_tilde_float),</span></div><div dir="ltr"><span>which adds them to the linked list x_xlist.</span></div><div dir="ltr"><br><span></span></div><div dir="ltr"><span>For example,</span></div><div dir="ltr"><span>suppose you have the following:</span></div><div dir="ltr"><br><span></span></div><div dir="ltr"><span>[0 0.1, 1 0.2(</span></div><div dir="ltr"><span>|</span></div><div dir="ltr"><span>[pipe]</span></div><div dir="ltr">|</div><div dir="ltr">[vline~]<br><span></span></div><div dir="ltr"><span>|</span></div><div dir="ltr"><span>[print~]</span></div><div dir="ltr"><br><span></span></div><div dir="ltr"><span>When you click the message box, [pipe] does the proper clock delay for</span></div><div dir="ltr"><span>each message: the "0" is scheduled for 0.1ms in the future, and the "1" is</span></div><div dir="ltr"><span>scheduled for 0.2ms.  But these delay times take less time to fire than it</span></div><div dir="ltr"><span>takes to compute a block.  So if [vline~] is calculating its output in blocks<br></span></div></div><div dir="ltr"><div dir="ltr">of 64 samples, when does it actually receive the output from [pipe~]?</div><div dir="ltr"><br></div><div dir="ltr">The answer is that Pd actually sends the "0" and "1" messages to [vline~]</div><div dir="ltr">one after the other, before it calculates the next block.  By "send" I mean it</div><div dir="ltr">calls the function vline_tilde_float with the float argument "0", and then it calls</div><div dir="ltr">vline_tilde_float with the float argument "1".  But before each of those calls, it updates the "sys_time" to be the time when that clock was set to go off.  So if the "0" was set to go off at "now + 0.1", Pd sets "now+0.1" to be the new system time, then it sends the "0" message to vline_tilde_float.  And before it sends "1", <br></div><div dir="ltr">it sets the sys_time to "now + 0.2".<br></div><div dir="ltr"><br></div><div dir="ltr">Let's go back to vline_tilde_float-- notice in the first line we're fetching the</div><div dir="ltr">sys_time.  And what is it going to be for our "0" message? As stated above, we</div><div dir="ltr">set it to "now + 0.1".  Great!  And when we process "1" message, we get "now + 0.2".  Thus, [vline~] adds those messages and their associated timings to the linked list.</div><div dir="ltr"><br></div><div dir="ltr">Finally, we do [vline~] perform routine.  It starts with the time equal to what it</div><div dir="ltr">was at the beginning of the block.  Then it loops through our block's samples</div><div dir="ltr">until it reaches a sample that corresponds to the time that an event in our</div><div dir="ltr">linked list needs to be triggered.  When we reach that sample, we jump to</div><div dir="ltr">the new value.<br></div><div dir="ltr"><br></div><div dir="ltr">It's the same process for ramps, except that vline~ calculates an increment</div><div dir="ltr">value for the ramp.<br></div><span></span></div><div dir="ltr"><span></span></div><div><br>  </div><div>After looking, I'm kind of curious what is most responsible for [vline~]</div><div dir="ltr">overhead.  I'd guess it's the math needed to set each ramp segment, but I'm not</div><div dir="ltr">certain.<span class="HOEnZb"><font color="#888888"><br></font></span></div><span class="HOEnZb"><font color="#888888"><div dir="ltr"><br></div><div dir="ltr">-Jonathan<br></div><div><br clear="none"><br clear="none"></div><div></div></font></span></div></div></div><div><div class="h5"><div> <div style="font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px"> <div style="font-family:HelveticaNeue,Helvetica Neue,Helvetica,Arial,Lucida Grande,sans-serif;font-size:16px"> <div dir="ltr"> <font face="Arial" size="2"> On Saturday, September 26, 2015 10:55 PM, i go bananas <<a href="mailto:hard.off@gmail.com" target="_blank">hard.off@gmail.com</a>> wrote:<br clear="none"> </font> </div>  <br clear="none"><br clear="none"> <div><div><div>I actually think Frank might have the my answer here.  <div><br clear="none"></div><div>What i'm noticing, is not an inconsistency in the length of the ramps.  It's an inconsisency in when they are first triggered.  This is for stuff like the initial click of a bassdrum, so you can even hear the difference quite clearly.  The line object jumps around, as it is being triggered on block boundaries, but the vline object is faithfully consistent in starting at the exact TIME i ask it to - regardless of blocksize, etc. </div><div><br clear="none"></div><div>The only logical answer i can see here, is the one Frank has given.  I'm scheduling drums using a clock controlled by metro.  </div><div><br clear="none"></div><div>So what i'm guessing that Frank is suggesting here, is that the scheduler is keeping a list of all the metro and delay bangs that should arrive in the upcoming block, and sceduling them to be hit while the block plays.  And what vline does, is it reads that list, and then schedules itself to be hit after the correct amount of logical time has elapsed.  </div><div><br clear="none"></div><div>And i would guess that the normal line object is not capable of that.  It just waits until block boundaries and starts its simple incrementation. </div><div><br clear="none"></div><div>So, going back to Jonathan's day-long block example, i can see now how that works.  the line can only be triggered once, at the start of the block (i still have doubts that it would actually stretch to the length of the block though.  I reckon a 50ms line is still gonna take 50ms. )  </div><div>But the vline has that linked list inbuilt, and it reads from the scheduler to see when it should be triggered.  So if you had the day-long block, then vline's linked list is gonna end up with a full day's worth of messages in it!  </div><div><br clear="none"></div><div>Anyway, i'll go back to the source code tomorrow and have another look.  But pretty sure that i now see how it is the ability to look ahead at metro scheduled events that gives vline the accuracy i need.  </div><div><br clear="none"></div><div>Thanks Matt for suggesting i look at the clock, and scheduler code, thanks Jonothan for the great example of the day long block - taking things to extremes like that is a good way to see how they work.  And thanks Frank for finally turning on that lightbulb and suggesting the role that metro was playing here.  </div><div><div><br clear="none"></div></div></div></div><br clear="none"><br clear="none"></div>  </div> </div>  </div></div></div></div></div></blockquote></div><br></div>