• 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
  • lacuna

    Hello,

    i am wrapping my head around how to control PD-patches sample accurately from a DAW?

    With Camomile?

    As this is a bit confusing, could someone help with some light please?

    For example:

    ** How to build a sample-accurate envelope, - triggered and modulated by a DAW? **

    I am using Linux, so cross-routing with Jack is an option, too.

    Probably somehow with [vline~] or [vphasor~]? This is sample accurate in the next block, isn't it? i.e. with latency-compensation in the DAW it is on point?

    Open Sound Control is not sample accurate, is it? Seems like the PD-sheduler does not handle OSC synchronous!?

    ( How to trigger a set of control-rate objects by an audio-signal sample accurate? What would be the port / the transition between the two?
    This isn't possible, is it?
    I guess it is, with [pd]{ [inlet~] [block~1] [unsig~] [outlet] } and [vline~]? )

    Do I need to patch the whole envelope with audio-rate objects?
    i.e. [vphasor~] instead of [vline~]?

    What is the way to go
    to merge PD with a DAW sample-accurately?
    DAW automation <--> PD control- and audio-objects.
    And audio-intermodulation of DAW & PD?

    posted in technical issues read more
  • lacuna

    @EEight
    very interesting question and project!
    This is some very basic concept, useful in many more cases.

    The compressor-trick doesn't seem it, as that compression would add another "effect" or "mutation" to the sound.

    Maybe something like:

    two inputs, RMS mesurement, matching the two in a specified smoothing-time-slope

    I'd be very happy if you would post your solution of level matching.

    posted in technical issues read more
  • lacuna

    fm

    posted in patch~ read more
  • lacuna

    @whale-av yes, [phasor~] *is *a ramp! I will try ...

    posted in technical issues read more
  • lacuna

    my ideas, before starting to make it probably more clear:
    what i would need:

    samplecounter to know when time is up
    and low pass filter to shape the ramp

    ?

    or
    samplecounter, calculate the ramp, do the ramp, time is up

    something like this? Probably there is already some abstraction for this or a really smart way to go?

    posted in technical issues read more
  • lacuna

    Time and target of the ramp should get calculated and executed several times in less than the 64 samples-grid of the message-domain sheduler [sic]

    I correct myself: like [vline~] with audio-inlets

    posted in technical issues read more
  • lacuna

    has anybody ever done this?
    any ideas on how to do that quick and efficient?

    posted in technical issues read more
  • lacuna

    [line]

    [f]
    [line~]
    [sig~]
    [snapshot~]
    [tabwrite~]
    [tabwrite]
    [tabsend~]
    [tabread]
    [tabread~]
    [tabread4~]
    [expr]

    not vanilla:
    [pack~]
    [unpack~]
    [unsig~]
    [speedlim]

    posted in technical issues read more
  • lacuna

    wow, can you even set this flag with [pd~]?

    posted in technical issues read more
  • lacuna

    [tabwrite~] writes to ram
    [writesf~] writes to disk.

    It depends on what you want to do with the recorded sound in realtime? How fast should it be?

    Generally spoken if you want to record audio over a long period of time it's common to use [writesf~] as memory space of ram is much smaller than diskspace (on PCs).

    posted in technical issues read more
  • lacuna

    [!= 0] and [spigot]

    posted in technical issues read more
Internal error.

Oops! Looks like something went wrong!