<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<style type="text/css" style="display:none;"> P {margin-top:0;margin-bottom:0;} </style>
</head>
<body dir="ltr">
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0); background-color: rgb(255, 255, 255);">
Maybe that text could be in the documentation :)</div>
<div>
<div id="appendonsend"></div>
<div style="font-family: Calibri, Helvetica, sans-serif; font-size: 12pt; color: rgb(0, 0, 0);">
<br>
</div>
<hr tabindex="-1" style="display:inline-block; width:98%">
<div id="divRplyFwdMsg" dir="ltr"><font face="Calibri, sans-serif" color="#000000" style="font-size: 11pt;" data-ogsc=""><b>De:</b> Pd-list <pd-list-bounces@lists.iem.at> em nome de Simon Iten <itensimon@gmail.com><br>
<b>Enviado:</b> terça-feira, 29 de outubro de 2019 06:20<br>
<b>Cc:</b> Pd-list <pd-list@lists.iem.at><br>
<b>Assunto:</b> Re: [PD] send~ receive~ throw~ catch~ inlet~ outlet~ latency</font>
<div> </div>
</div>
<div>
<div dir="auto">Johannes, thank you so much for your in depth answer! i hope this will also serve well for others (hence my verbose mail subject)
<div dir="auto"><br>
</div>
<div dir="auto">appreciated!!</div>
</div>
<br>
<div class="x_gmail_quote">
<div dir="ltr" class="x_gmail_attr">On Tue, Oct 29, 2019, 10:15 IOhannes m zmoelnig <<a href="mailto:zmoelnig@iem.at" style="">zmoelnig@iem.at</a>> wrote:<br>
</div>
<blockquote class="x_gmail_quote" style="margin:0 0 0 .8ex; border-left:1px #ccc solid; padding-left:1ex">
On 28.10.19 23:50, Simon Iten wrote:<br>
> hi there,<br>
> <br>
> can somebody clear up something for me regarding tilde “wireless” objects and subpatches?<br>
> <br>
> the G05.execution.order example mentions possible 64-sample delays in send~ receive~ and throw~ catch~<br>
> <br>
<br>
<br>
first let's make clear what is causing latency.<br>
e.g. consider three signal objects that are chained up "A->B->C".<br>
when turning DSP "on", those objects will start calculating samples<br>
based on their input.<br>
every 1.45ms ("each DSP tick") all 3 objects will need to calculate 64<br>
samples.<br>
<br>
if "A" does its calculations before "B" and "B" before "C", then the 3<br>
objects will do their calculations with zero latency. that is: if all<br>
objects just pass their input samples to their output, and at the<br>
beginning of the DSP tick the "A" objects gets a single sample value of<br>
1 (with all other samples before and after being 0), then it will read<br>
this pulse and pass it on to "B" which will read the pulse and pass it<br>
on the "C" which in turn will pass it to its output. once all the<br>
calculations are done, the pulse has passed through all objects.<br>
<br>
conversely, what happens if "C" does its calculation before "B" and "B"<br>
before "A"? we still feed the pulse to "A", but since "C" is being<br>
executed first, its input has all zeros which it passes to the final<br>
output, then "B" will read all zeros, passing them to its output, and<br>
finally "A" will pass the pulse to its output.<br>
all DSP calculations are now done, and at the output we get silence (but<br>
there's a pulse lingering between "A" and "B")<br>
in the next DSP tick, "C" will first read its input (which is the output<br>
that "B" 'just' (in the last DSP-tick) created, that is: zeros) and pass<br>
it on; then "B" will pass its input (which is the output that "A" just<br>
created: a pulse) and pass it on.<br>
all DSP calculations are now done, and at the output we get silence (but<br>
now the pulse is pulse lingering between "B" and "C").<br>
in the next DSP tick, "C" will again read its input (which is the output<br>
that "B" just created: a pulse).<br>
once all DSP calculations are done, the output (of "C") will be a pulse.<br>
<br>
comparing this to the 1st A, 2nd B, 3rd C calculation above, we see that<br>
the output is late by 2 DSP ticks, which is 2 blocks (each 64 samples,<br>
usually).<br>
<br>
<br>
<br>
obviously it is better to do the calculations in the correct order,<br>
because it allows you to achieve zero latency in a whole chain of objects.<br>
So Pd tries hard to do exactly that: if two objects are connected with a<br>
signal connection, the source object will always be processed before the<br>
sink object.<br>
this is done by the Pd-scheduler that sorts the DSP graph (as a directed<br>
acyclic graph that expresses the inter-object dependencies) whenever you<br>
turn DSP "on"<br>
<br>
incidentally, this also works for meta-objects ("abstractions" or<br>
"sub-patches"): if you connect two abstractions with signal connections<br>
("X->Y"), then the *entire* source abstraction (*all* signal objects<br>
within "X") will be processed before the entire sink abstraction (*all*<br>
signal objects withing "Y").<br>
<br>
<br>
now what's different with implicit connections ([s~], [r~],...)?<br>
simply put: the Pd-scheduler (that does the sorting of the DSP<br>
calculations) does not know that a [s~ foo] object is connected to a<br>
[receive~ foo].<br>
these two objects are connected via their own logic, but the<br>
Pd-scheduler doesn't know anything about their inner logic and just<br>
looks at their explicit connections to determine which object needs to<br>
be evaluated first.<br>
<br>
depending on the patch, there are three possibilities:<br>
1) somehow the [r~ foo] is connected explicitely to [s~ foo], typically<br>
if you are doing feedback.<br>
in this case, the [r~] must be processed before the [s~], so the [s~]<br>
didn't have the chance yet to generate the new sample block, leaving<br>
[r~] with the last sample block - introducing a delay of one block.<br>
<br>
2) somehow the [s~ foo] is connected explicitely to [r~ foo]. this is a<br>
bit harder to acchieve, since [s~] has no outlet and [r~] to inlet.<br>
however, if we put both into abstractions/subpatches with iolet~s, then<br>
we can connect these iolets. since the entire source abstraction is<br>
processed before the entire sink abstraction, any [s~] in the source<br>
abstraction will also be processed before any [r~] in the sink abstraction.<br>
whenever [r~] does it's thing, [s~] will already have produced a new<br>
block of samples, so [r~] will get the fresh stuff and no delay occurs.<br>
<br>
3) the [s~] and [r~] are not connected at all (e.g. "[adc~ 1]->[s~ foo]<br>
  [r~ foo]->[dac~ 1]")<br>
in this case, Pd doesn't know whether it should first process the [s~]<br>
or the [r~] and will pick one "randomly". depending on which it picked,<br>
you will get a block delay or not.<br>
this is the "fan out" for signals.<br>
<br>
<br>
> i don’t fully get the strategy to avoid them.<br>
> do i have to put them into a subpatch and connect inlets~ and outlets~<br>
<br>
yes.<br>
the *only* safe way to guarantee a certain order of execution for signal<br>
objects is by making their dependencies explicit.<br>
the only way to make dependencies explicit is to use signal connections<br>
(which involves inlet~ and outlet~ when it comes to subpatches)<br>
<br>
> (somewhat defeating the purpose of the s~ and r~ objects)<br>
<br>
only somewhat.<br>
there are multiple purposes of [s~] and [r~] objects.<br>
avoiding explicit connections is the worst use.<br>
<br>
> also, inlet~ and outlet~ never add latency, right?<br>
<br>
jein.<br>
<br>
they don't add latency by themselves, as they are only crutches to make<br>
explicit connections between windows.<br>
<br>
but if your subpatch runs on a higher blocksize (e.g. 1024 instead of<br>
the default 64, using [block~ 1024]) then the [inlet~]/[outlet~] objects<br>
are the place were the actual re-blocking happens.<br>
<br>
gmasdrt<br>
IOhannes<br>
<br>
_______________________________________________<br>
<a href="mailto:Pd-list@lists.iem.at" target="_blank" rel="noreferrer" style="">Pd-list@lists.iem.at</a> mailing list<br>
UNSUBSCRIBE and account-management -> <a href="https://lists.puredata.info/listinfo/pd-list" rel="noreferrer noreferrer" target="_blank" style="">
https://lists.puredata.info/listinfo/pd-list</a><br>
</blockquote>
</div>
</div>
</div>
</body>
</html>