• lacuna

    @Nicolas-Danet said:

    control messages and compute audio vectors of the DSP graph are interleaved operations. The internal audio vector size is 64.

    [64][control][64][control][64][control][64][control]
    

    Ok, i see.
    But I read control messages are first, then audio. f.e. [loadbang] is proceeded before an upcoming audio-block.
    And [vline~] is calculated and "drawn" before and "modulating" the *following * audio blocks.

    [control][64][control][64][control][64][control][64]
    

    What's happen in a 1 sample reblocked subpatch? In short, instead of compute 1 vector of 64 samples, it computes 64 times following a vector of 1 sample.

    And there is no way to change this interval rate of 64?
    Is upsampling in a subpatch increasing the computation time-interval of control-messages?

    The tricky stuff with real time audio is not to do the things fast, but do things fast at the right time. Wait the sound in, deliver the sound out, compute the next sound and wait. When i benchmark my fork for instance, most of the time is spent in sleeping!

    I see. In the analog world it is very different. This is why we have the buffer-latency in digital everywhere:

    ...incoming audio-samples in blocks, computation, audio out, and again...
    

    And the control-domain every 64 samples.
    For me as "user" of PD this is confusing.
    So every object with a [v ...] will be sampleaccurate on point in upcoming audio-blocks, as long as it is not needed more often then 64 samples later!??? i.e. as long it is not starting several times in a smaller interval then 64 samples?

    posted in technical issues read more
  • lacuna

    @EEight said:

    @lacuna said:
    I just see this flag on linux:
    -nosleep -- spin, don't sleep (may lower latency on multi-CPUs)

    Oh yes and there are startup flags for loading a different scheduler (I corrected this in my first post now)
    https://puredata.info/docs/faq/commandline

      -rt or -realtime -- use real-time priority
      -nrt             -- don't use real-time priority
      -sleep           -- sleep when idle, don't spin (true by default)
      -nosleep         -- spin, don't sleep (may lower latency on multi-CPUs)
      -schedlib <file> -- plug in external scheduler
      -extraflags <s>  -- string argument to send schedlib
      -batch           -- run off-line as a batch process
      -nobatch         -- run interactively (true by default) 
    

    Not sure, would be interested to know too.

    @EEight output of full text search of sleep with grep in pd's source folder -nri flags set:
    https://pastebin.com/3mBw6Mnj

    
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/u_pdsend.c:86:            sleep (nretry < 5 ? 1 : 5);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_stuff.h:65:extern int sys_sleepgrain;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_stuff.h:163:EXTERN void sys_microsleep(int microsec);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_stuff.h:369:EXTERN int* get_sys_sleepgrain(void);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:58:int sys_nosleep = 0;  /* skip all "sleep" calls and spin instead */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:115:int* get_sys_sleepgrain() { return &sys_sleepgrain; }
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:424:"-sleepgrain <n>  -- specify number of milliseconds to sleep when idle\n",
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:520:"-sleep           -- sleep when idle, don't spin (true by default)\n",
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:521:"-nosleep         -- spin, don't sleep (may lower latency on multi-CPUs)\n",
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:732:        else if (!strcmp(*argv, "-sleepgrain"))
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:737:            sys_sleepgrain = 1000 * atof(argv[1]);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:1242:        else if (!strcmp(*argv, "-sleep"))
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:1244:            sys_nosleep = 0;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:1247:        else if (!strcmp(*argv, "-nosleep"))
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_main.c:1249:            sys_nosleep = 1;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:202:extern int sys_nosleep;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:204:/* sleep (but cancel the sleeping if pollem is set and any file descriptors are
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:207:sleep. */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:208:static int sys_domicrosleep(int microsec, int pollem)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:226:          perror("microsleep select");
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:242:        Sleep(microsec/1000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:244:        usleep(microsec);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:251:    /* sleep (but if any incoming or to-gui sending to do, do that instead.)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:253:void sys_microsleep(int microsec)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:256:    sys_domicrosleep(microsec, 1);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_inter.c:909:    int didsomething = sys_domicrosleep(0, 1);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:16:    correct thread synchronization (by defining THREADSIGNAL) or just sleeping
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:21:    switch to usleep in s_inter.c
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:91:#include <windows.h>    /* for Sleep() */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:549:            sys_microsleep(sys_sleepgrain);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:550:            if (!pa_stream)     /* sys_microsleep() may have closed device */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:591:            sys_microsleep(sys_sleepgrain);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_pa.c:592:            if (!pa_stream)     /* sys_microsleep() may have closed device */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_oss.c:672:            sys_microsleep(2000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:105:/* if more than this sleep detected, should be more than periodsize/samplerate ??? */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:106:static double sleep_time;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:340:  sleep_time =  (float) alsamm_period_size/ (float) alsamm_sr;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:798:      sleep(1);       /* wait until the suspend flag is released */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:1336:  if ((timenow = sys_getrealtime()) > (timelast + sleep_time))
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsamm.c:1342:             timenow,timelast,sleep_time,(timelast + sleep_time));
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/s_audio_alsa.c:691:        sys_microsleep(5000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:23:int sys_usecsincelastsleep(void);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:24:int sys_sleepgrain;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:442:will now sleep. */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:454:    if (sys_sleepgrain < 100)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:455:        sys_sleepgrain = sys_schedadvance/4;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:456:    if (sys_sleepgrain < 100)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:457:        sys_sleepgrain = 100;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:458:    else if (sys_sleepgrain > 5000)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:459:        sys_sleepgrain = 5000;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:477:               the machine sleeps.  */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:539:                    /* if even that had nothing to do, sleep. */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:541:                    sys_microsleep(sys_sleepgrain);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:574:        Sleep(1000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/src/m_sched.c:576:        sleep(1);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptwinmm.c:67:PMEXPORT void Pt_Sleep(int32_t duration)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptwinmm.c:69:    Sleep(duration);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptmacosx_mach.c:128:void Pt_Sleep(int32_t duration)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptmacosx_mach.c:130:    usleep(duration * 1000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptmacosx_cf.c:137:void Pt_Sleep(int32_t duration)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptmacosx_cf.c:139:    usleep(duration * 1000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptlinux.c:14:of sleeping when realtime threads request a sleep of <=2ms (as a way 
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptlinux.c:132:void Pt_Sleep(int32_t duration)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/ptlinux.c:134:    usleep(duration * 1000);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/porttime.h:82:    Pt_Sleep() pauses, allowing other threads to run.
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/porttime/porttime.h:88:PMEXPORT void Pt_Sleep(int32_t duration);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/portmidi/pm_mac/pmmacosxcm.c:492:            usleep((useconds_t) 
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portmidi/patches/mac_limit_rate_override.patch:52:             usleep((useconds_t) 
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/win/pa_win_util.c:102:void Pa_Sleep( long msec )
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/win/pa_win_util.c:104:    Sleep( msec );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:108:void Pa_Sleep( long msec )
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:110:#ifdef HAVE_NANOSLEEP
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:116:    nanosleep(&req, &rem);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:117:    /* XXX: Try sleeping the remaining time (contained in rem) if interrupted by a signal? */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:120:        {                   /* to usleep must be < 1000000.   */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:121:        usleep( 999000 );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:124:    usleep( msec * 1000 );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:599:        /* Test before and after in case whatever underlying sleep call isn't interrupted by pthread_cancel */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:601:        Pa_Sleep( intervalMsec );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:644:            PA_DEBUG(( "%s: Watchdog sleeping for %lu msecs before unthrottling\n", __FUNCTION__, th->throttledSleepTime ));
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:645:            Pa_Sleep( th->throttledSleepTime );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/os/unix/pa_unix_util.c:704:        Pa_Sleep( intervalMsec );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/wmme/pa_win_wmme.c:2185:    unsigned long throttledSleepMsecs;
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/wmme/pa_win_wmme.c:2565:    /* time to sleep when throttling due to >100% cpu usage.
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/wmme/pa_win_wmme.c:2567:    stream->throttledSleepMsecs =
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/wmme/pa_win_wmme.c:3194:                            /* sleep to give other processes a go */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/wmme/pa_win_wmme.c:3195:                            Sleep( stream->throttledSleepMsecs );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c:395:      /* No match yet, so let's sleep and try again. */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c:396:      Pa_Sleep( 100 );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.h:69:#define PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL (5)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c:454:             Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c:535:             Pa_Sleep( PA_MAC_BLIO_BUSY_WAIT_SLEEP_INTERVAL );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core_blocking.c:607:            Pa_Sleep( msecPerBuffer );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/coreaudio/pa_mac_core.c:2722:       Pa_Sleep( 100 );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/asio/pa_asio.cpp:3401:        Sleep(1);
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/alsa/pa_linux_alsa.c:1129:        Pa_Sleep( 10 );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/alsa/pa_linux_alsa.c:2759:        /* self->threading.throttledSleepTime = (unsigned long) (minFramesPerHostBuffer / sampleRate / 4 * 1000); */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/alsa/pa_linux_alsa.c:3831:                Pa_Sleep( 1 ); /* avoid hot loop */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/alsa/pa_linux_alsa.c:3849:            if( timeouts > 1 ) /* sometimes device times out, but normally once, so we do not sleep any time */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/hostapi/alsa/pa_linux_alsa.c:3851:                Pa_Sleep( 1 ); /* avoid hot loop */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/src/common/pa_util.h:152:/* void Pa_Sleep( long msec );  must also be implemented in per-platform .c file */
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/include/portaudio.h:1211:/** Put the caller to sleep for at least 'msec' milliseconds. This function is
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/include/portaudio.h:1215: The function may sleep longer than requested so don't rely on this for accurate
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/include/portaudio.h:1218:void Pa_Sleep( long msec );
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/include/pa_win_wmme.h:64:    to THREAD_PRIORITY_NORMAL and sleeps the thread if the CPU load exceeds 100%
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/portaudio/portaudio/include/pa_linux_alsa.h:91:/** Set the maximum number of times to retry opening busy device (sleeping for a
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x5.htm:599:<P> In linux, a "-nosleep" flag causes Pd to poll instead of sleeping as it
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x5.htm:798:<P> Fixed a thread-safety problem in sys_microsleep().
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x5.htm:1224:the controlling parameter for MIDI jitter is "-sleepgrain", which specifies
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x5.htm:1225:the interval of time Pd sleeps when it believes it's idle.
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x5.htm:1373:<P> -sleepgrain: if you aren't using audio I/O, this can reduce time jitter in
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:488:scheduling; "-sleepgrain 1" sets the sleep grain to 1 (see under MIDI below),
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:489:and typing "-rt -sleepgrain 1" does both.
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:527:-sleepgrain &lt;n&gt;  -- specify number of milliseconds to sleep when idle
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:573:-nosleep         -- never relinquish CPU (only for multiprocessors!)
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:610:<H4> MIDI and sleepgrain</H4>
    /pd-0.50-2.src.tar.gz.extracted/pd-0.50-2/doc/1.manual/x3.htm:619:<P> The "sleepgrain" controls how long (in milliseconds) Pd sleeps between
    

    good night sweet dreams

    posted in technical issues read more
  • lacuna

    @djpersonalspace here is exactly the same patch with comments added in detail:
    quant_step_seq_forum_2morecomments.pd

    posted in technical issues read more
  • lacuna

    @djpersonalspace
    It's commented on almost every step.
    Some arrays are just for visualisation.
    The [% 10] and [mod 10] are there just for understanding the [expr] better.

    Read the patch from the top left to the lower right.

    I guess it is not efficient at all, could be made easier, - these are just my thoughts sketched.

    The main idea is: increase the resolution by 10 and round up if the remainer of /10 is >=5, else round down.
    A complicated way to round 3.7 up and 6.2 down!

    Increasing the resolution by 2 and distinguishing between even and odd numbers might be more efficient and would make the decision symmetric
    (even vs. uneven / set current step or one step later) ... ( now it is 1234 vs 56789, these are 4 cases vs. 5 and this is not a symmetrical decision in the center of the two beats)

    Your BPM conversion might be more true.

    Ask if you have questions.

    posted in technical issues read more
  • lacuna

    Hello, :sparkles:

    this is going to be a long one.
    After years of using PD, I am still confused about its' timing and schedueling.

    I have collected many snippets from here and there about this topic,
    -wich all together are really confusing to me.

    *I think it is very important to understand how timing works in detail for low-level programming … *

    (For example the number of heavy jittering sequencers in hard and software make me wonder what sequencers are made actually for ? lol )

    This is a collection of my findings regarding this topic, a bit messy and with confused questions.

    I hope we can shed some light on this.


    :lips: :eyes: :ear:

    • a)

    The first time, I had issues with the PD-scheduler vs. how I thought my patch should work is described here:
    https://forum.pdpatchrepo.info/topic/11615/bang-bug-when-block-1-1-1-bang-on-every-sample

    The answers where:

    „
    [...] it's just that messages actually only process every 64 samples at the least. You can get a bang every sample with [metro 1 1 samp] but it should be noted that most pd message objects only interact with each other at 64-sample boundaries, there are some that use the elapsed logical time to get times in between though (like vsnapshot~)
    also this seems like a very inefficient way to do per-sample processing..
    https://github.com/sebshader/shadylib http://www.openprocessing.org/user/29118
    seb-harmonik.ar posted about a year ago , last edited by seb-harmonik.ar about a year ago 
    • 1 
     whale-av 
    @lacuna An excellent simple explanation from @seb-harmonik.ar.
    Chapter 2.5 onwards for more info....... http://puredata.info/docs/manuals/pd/x2.htm
    David.
    “
    

    There is written: http://puredata.info/docs/manuals/pd/x2.htm

    „2.5. scheduling 
    Pd uses 64-bit floating point numbers to represent time, providing sample accuracy and essentially never overflowing. Time appears to the user in milliseconds. 
    2.5.1. audio and messages 
    Audio and message processing are interleaved in Pd. Audio processing is scheduled every 64 samples at Pd's sample rate; at 44100 Hz. this gives a period of 1.45 milliseconds. You may turn DSP computation on and off by sending the "pd" object the messages "dsp 1" and "dsp 0." 
    In the intervals between, delays might time out or external conditions might arise (incoming MIDI, mouse clicks, or whatnot). These may cause a cascade of depth-first message passing; each such message cascade is completely run out before the next message or DSP tick is computed. Messages are never passed to objects during a DSP tick; the ticks are atomic and parameter changes sent to different objects in any given message cascade take effect simultaneously. 
    In the middle of a message cascade you may schedule another one at a delay of zero. This delayed cascade happens after the present cascade has finished, but at the same logical time. 
    2.5.2. computation load 
    The Pd scheduler maintains a (user-specified) lead on its computations; that is, it tries to keep ahead of real time by a small amount in order to be able to absorb unpredictable, momentary increases in computation time. This is specified using the "audiobuffer" or "frags" command line flags (see getting Pd to run ). 
    If Pd gets late with respect to real time, gaps (either occasional or frequent) will appear in both the input and output audio streams. On the other hand, disk strewaming objects will work correctly, so that you may use Pd as a batch program with soundfile input and/or output. The "-nogui" and "-send" startup flags are provided to aid in doing this. 
    Pd's "realtime" computations compete for CPU time with its own GUI, which runs as a separate process. A flow control mechanism will be provided someday to prevent this from causing trouble, but it is in any case wise to avoid having too much drawing going on while Pd is trying to make sound. If a subwindow is closed, Pd suspends sending the GUI update messages for it; but not so for miniaturized windows as of version 0.32. You should really close them when you aren't using them. 
    2.5.3. determinism 
    All message cascades that are scheduled (via "delay" and its relatives) to happen before a given audio tick will happen as scheduled regardless of whether Pd as a whole is running on time; in other words, calculation is never reordered for any real-time considerations. This is done in order to make Pd's operation deterministic. 
    If a message cascade is started by an external event, a time tag is given it. These time tags are guaranteed to be consistent with the times at which timeouts are scheduled and DSP ticks are computed; i.e., time never decreases. (However, either Pd or a hardware driver may lie about the physical time an input arrives; this depends on the operating system.) "Timer" objects which meaure time intervals measure them in terms of the logical time stamps of the message cascades, so that timing a "delay" object always gives exactly the theoretical value. (There is, however, a "realtime" object that measures real time, with nondeterministic results.) 
    If two message cascades are scheduled for the same logical time, they are carried out in the order they were scheduled. 
    “ 
    

    [block~ smaller then 64] doesn't change the interval of message-control-domain-calculation?,
    Only the size of the audio-samples calculated at once is decreased?
    Is this the reason [block~] should always be … 128 64 32 16 8 4 2 1, nothing inbetween, because else it would mess with the calculation every 64 samples?
    How do I know which messages are handeled inbetween smaller blocksizes the 64 and which are not?

    How does [vline~] execute?
    Does it calculate between sample 64 and 65 a ramp of samples with a delay beforehand, calculated in samples, too - running like a "stupid array" in audio-rate?

    While sample 1-64 are running, PD does audio only?

    [metro 1 1 samp]  
    

    How could I have known that? The helpfile doesn't mention this. (Offtopic: actually the whole forum is full of pd-vocabular-questions)
    How is this calculation being done?
    But you can „use“ the metro counts every 64 samples only, don't you?

    Is the timing of [metro] exact? Will the milliseconds dialed in be on point or jittering with the 64 samples interval?
    Even if it is exact the upcoming calculation will happen in that 64 sample frame!?


    b )

    :point_right: :ok_hand:
    There are [phasor~], [vphasor~] and [vphasor2~] … and [vsamphold~]
    https://forum.pdpatchrepo.info/topic/10192/vphasor-and-vphasor2-subsample-accurate-phasors

    “Ive been getting back into Pd lately and have been messing around with some granular stuff. A few years ago I posted a [vphasor.mmb~] abstraction that made the phase reset of [phasor~] sample-accurate using vanilla objects. Unfortunately, I'm finding that with pitch-synchronous granular synthesis, sample accuracy isn't accurate enough. There's still a little jitter that causes a little bit of noise. So I went ahead and made an external to fix this issue, and I know a lot of people have wanted this so I thought I'd share. 
    [vphasor~] acts just like [phasor~], except the phase resets with subsample accuracy at the moment the message is sent. I think it's about as accurate as Pd will allow, though I don't pretend to be an expert C programmer or know Pd's api that well. But it seems to be about as accurate as [vline~]. (Actually, I've found that [vline~] starts its ramp a sample early, which is some unexpected behavior.)
    […]
    “
    

    • c)

    :yellow_heart: :blue_heart: :green_heart:
    Later I discovered that PD has jittery Midi because it doesn't handle Midi at a higher priority then everything else (GUI, OSC, message-domain ect.)


    • d)

    :fire:
    So I looked into the sources of PD:

    scheduler with m_mainloop()
    https://github.com/pure-data/pure-data/blob/master/src/m_sched.c

    And found this paper

    Scheduler explained (in German): 
    https://iaem.at/kurse/ss19/iaa/pdscheduler.pdf/view
    

    https://iaem.at/kurse/ss19/iaa/pdscheduler.pdf/view

    wich explains the interleaving of control and audio domain as in the text of @seb-harmonik.ar with some drawings
    plus the distinction between the two (control vs audio / realtime vs logical time / xruns vs burst batch processing).
    And the "timestamping objects" listed below.

    And the mainloop:

    Loop
    - messages (var.duration)
    - dsp (rel.const.duration)
    - sleep
    

    With
    [block~ 1 1 1]
    calculations in the control-domain are done between every sample? But there is still a 64 sample interval somehow?
    Why is [block~ 1 1 1] more expensive? The amount of data is the same!? Is this the overhead which makes the difference? Calling up operations ect.?


    Timing-relevant objects
    from iemlib:

    [...]
    iem_blocksize~   blocksize of a window in samples
    iem_samplerate~  samplerate of a window in Hertz 
    
    
    ------------------ t3~ - time-tagged-trigger --------------------
    -- inputmessages allow a sample-accurate access to signalshape --
    t3_sig~          time tagged trigger sig~
    t3_line~         time tagged trigger line~
    
    
    --------------- t3 - time-tagged-trigger  ---------------------
    ----------- a time-tag is prepended to each message -----------
    ----- so these objects allow a sample-accurate access to ------
    ---------- the signal-objects t3_sig~ and t3_line~ ------------
    t3_bpe           time tagged trigger break point envelope
    t3_delay         time tagged trigger delay
    t3_metro         time tagged trigger metronom
    t3_timer         time tagged trigger timer
    
    [...]
    

    What are different use-cases of [line~] [vline~] and [t3_line~]?
    And of [phasor~] [vphasor~] and [vphasor2~]?

    When should I use [block~ 1 1 1] and when shouldn't I?

    [line~] starts at block boundaries defined with [block~] and ends in exact timing?
    [vline~] starts the line within the block?
    and [t3_line~]???? Are they some kind of interrupt? Shortcutting within sheduling???


    • c) again)

    :airplane:

    https://forum.pdpatchrepo.info/topic/1114/smooth-midi-clock-jitter/2

    I read this in the html help for Pd: 
    „
    MIDI and sleepgrain
    In Linux, if you ask for "pd -midioutdev 1" for instance, you get /dev/midi0 or /dev/midi00 (or even /dev/midi). "-midioutdev 45" would be /dev/midi44. In NT, device number 0 is the "MIDI mapper", which is the default MIDI device you selected from the control panel; counting from one, the device numbers are card numbers as listed by "pd -listdev."
    The "sleepgrain" controls how long (in milliseconds) Pd sleeps between periods of computation. This is normally the audio buffer divided by 4, but no less than 0.1 and no more than 5. On most OSes, ingoing and outgoing MIDI is quantized to this value, so if you care about MIDI timing, reduce this to 1 or less.
    „
    

    Why is there the „sleep-time“ of PD? For energy-saving??????
    This seems to slow down the whole process-chain?

    Can I control this with a startup flag or from withing PD? Or only in the sources?

    There is a startup-flag for loading a different scheduler, wich is not documented how to use.


    • e)

    :walking:
    [pd~] helpfile says:

    ATTENTION: DSP must be running in this process for the sub-process to run. This is because its clock is slaved to audio I/O it gets from us!
    

    Doesn't [pd~] work within a Camomile plugin!?

    How are things scheduled in Camomile? How is the communication with the DAW handled?


    • f)

    :swimmer:
    and slightly off-topic:
    There is a batch mode:
    https://forum.pdpatchrepo.info/topic/11776/sigmund-fiddle-or-helmholtz-faster-than-realtime/9


    Sorry for the mess!
    Could you please help me to sort things a bit? Mabye some real-world examples would help, too.

    :cat2:

    posted in technical issues read more
  • lacuna

    @whale-av thank you, good idea, I will try.
    (Not using Ableton live at all)

    as far as I see ths is not "data on every DSP tick". What did you want to say with this?
    It works differently:
    there has been this presentation at Linux Audio Conference 18:
    https://media.ccc.de/v/lac2018-42-ableton_link_a_technology_to_synchronize_music_software

    Not sure how accurate this gets. as there seems to be a lot of "average" "time filtering", "guessing" and it is about beats, not samples.

    The ease of use seems really cool!

    .
    I am still confused about the scheduler of PD:

    sample accuracy within Pure Data and the ports to the environment...
    Message domain, audio-rate, timestamps, block-boundaries, scheduler, ect.
    But I think that I will post another thread about this.
    As this is essential to understand programming in PD and there seems to be a lot of confusion about it even for advanced PD users, because the perception is most of the times "allright it works", not being picky in exact timing.

    posted in technical issues read more
  • lacuna

    @djpersonalspace and I messed with the BPM

    posted in technical issues read more
  • lacuna

    technically speaking, PD patches are open source all the time!? How could you close the source of a running patch? Not sure about the license restrictions of LibPD ?

    There was another post about PD licenses: https://forum.pdpatchrepo.info/topic/7993/licensing-freeverb-externals-limitations/7

    posted in Off topic read more
  • lacuna

    quant_step_seq_forum_2.pd

    voilà 4 vanilla

    (edit: increasing the resolution 2 times instead of 10 might be more efficient)

    and see https://forum.pdpatchrepo.info/topic/12378/arperatus

    posted in technical issues read more
  • lacuna

    @EEight ...
    Buchla Dual Signal Leveler Model 172
    https://www.modulargrid.net/u/la-67-172
    ok actually these "are" compressors

    posted in technical issues read more

Internal error.

Oops! Looks like something went wrong!