I found this behaviour slightly surprising, but on reflection it makes sense. Pd doesn't seem to check deeply into subpatches when looking for DSP feedback loops.
I started making a simple waveguide synth and decided, for a change, to work on the feedback mechanism inside another subpatch. I kept getting DSP loop error even though the signal path contains a [s~] and unique matching [r~]. Making the feedback loop require a [send~] and [receive~] in the outermost block seems to defeat the use of smaller blocksizes in subpatches.
Anyone care to comment on this (attached example). Or am I understanding this incorrectly?
Cheers. Andy
Hallo, padawan12 hat gesagt: // padawan12 wrote:
I found this behaviour slightly surprising, but on reflection it makes sense. Pd doesn't seem to check deeply into subpatches when looking for DSP feedback loops.
I started making a simple waveguide synth and decided, for a change, to work on the feedback mechanism inside another subpatch. I kept getting DSP loop error even though the signal path contains a [s~] and unique matching [r~]. Making the feedback loop require a [send~] and [receive~] in the outermost block seems to defeat the use of smaller blocksizes in subpatches.
I'm away from Pd so I cannot check your patch, but your description sounds like you're getting your execution order wrong by trying to force a certain order through subpatches although you have a feedback-delay ("recirculating delay")
You need to be aware that subpatches are evaluated in the order, the signal cords specify.
[pd sig1~] || || [pd sig2~]
Everything in [pd sig1~] will be calculated before everything in sig2~. But if you have a *feedback'd* delwrite~ in sig1~, fed from a delread~ in sig2~, then you'll get a dsp loop, because while it's okay to have the delwrite~ before the delread~ in the DSP graph (and actually it's wanted normally), with feedback you also have a read (catch~ or receive~) before the write (throw~ or send~) and in combination this is not possible in Pd as in the end it would be the same as this loop:
[r~ a] [r~ b] | | [a~] [b~] | | [s~ b] [s~ a]
or [a~]X[b~]. Which should come first?
Also see these two book excerpts: http://www.crca.ucsd.edu/~msp/techniques/latest/book-html/node120.html http://www.crca.ucsd.edu/~msp/techniques/latest/book-html/node121.html
Frank Barknecht _ ______footils.org_ __goto10.org__
Hallo, Frank Barknecht hat gesagt: // Frank Barknecht wrote:
I'm away from Pd so I cannot check your patch, but your description sounds like you're getting your execution order wrong by trying to force a certain order through subpatches although you have a feedback-delay ("recirculating delay")
Now I could take a look at your patches and it's exactly as I guessed. You even did the [pd a~]X[pd b~] dsp-loop construct, congrats! ;)
Note that this has nothing to do with Pd being "shallow" in regard to subpatches and dsp-loops, but instead the opposite is true: subpatches that are connected by signal-connections *define* the order of the dsp-graph.
Pd automatically avoids the loop in dsp-loop-example2.pd by enforcing a minimum delay time of one block between [r~ noloop] and [s~ noloop], which you can hear if you try to play a note that requires a lower delay time, e.g. midi note 30 and above. They will all have the same frequency.
Frank Barknecht _ ______footils.org_ __goto10.org__
Hallo, Frank Barknecht hat gesagt: // Frank Barknecht wrote:
Now I could take a look at your patches and it's exactly as I guessed. You even did the [pd a~]X[pd b~] dsp-loop construct, congrats! ;)
... which in its simplest case looks like in attached patch.
Frank Barknecht _ ______footils.org_ __goto10.org__
Like Frank, I haven't had a chance to check you patch..but wasn't there something about the creation order of these things which makes a difference? I remember getting *very* frustrated by this once.
d.
padawan12 wrote:
I found this behaviour slightly surprising, but on reflection it makes sense. Pd doesn't seem to check deeply into subpatches when looking for DSP feedback loops.
I started making a simple waveguide synth and decided, for a change, to work on the feedback mechanism inside another subpatch. I kept getting DSP loop error even though the signal path contains a [s~] and unique matching [r~]. Making the feedback loop require a [send~] and [receive~] in the outermost block seems to defeat the use of smaller blocksizes in subpatches.
Hallo, Derek Holzer hat gesagt: // Derek Holzer wrote:
Like Frank, I haven't had a chance to check you patch..but wasn't there something about the creation order of these things which makes a difference? I remember getting *very* frustrated by this once.
Actually Andy's problem is not related to this. He is using explicit ordering using dsp-connected subpatches, the creation order doesn't matter in this case.
Frank Barknecht _ ______footils.org_ __goto10.org__
But it is true that creation order affects this? Can you explain how, since I could never quite get it worked out properly and it cost me many hours and maybe even a few gray hairs ;-)
d.
Frank Barknecht wrote:
Hallo, Derek Holzer hat gesagt: // Derek Holzer wrote:
Like Frank, I haven't had a chance to check you patch..but wasn't there something about the creation order of these things which makes a difference? I remember getting *very* frustrated by this once.
Actually Andy's problem is not related to this. He is using explicit ordering using dsp-connected subpatches, the creation order doesn't matter in this case.
Ciao
Hallo, Derek Holzer hat gesagt: // Derek Holzer wrote:
But it is true that creation order affects this? Can you explain how, since I could never quite get it worked out properly and it cost me many hours and maybe even a few gray hairs ;-)
It's similar to normal messages, just replace [trigger] with [pd x] if you want explicit ordering.
Whereas in the message world, unknown ordering of "fanned" connections is the problem, that is solved with [trigger ...], in the signal world, non-local connections like s~, throw~ or delwrite~ are possible culprits that may introduce block-sized delays.
The basic problem is, that not all dsp-objects are calulated at the same time. They are calculated in the same block of samples, but if you have two signal objects one has to be calculated before the other.
This ordering is easy if you have direct connections:
[noise~] | [lop~ 5] |
[noise~ 1] will be calculated first, then [lop~ 5] can filter the result as input.
Or as Miller puts it:
Although the tilde objects in a patch may have a complicated topology of audio connections, in reality Pd executes them all in a sequential order, one after the other, to compute each block of audio output. This linear order is guaranteed to be compatible with the audio interconnections, in the sense that no tilde object's computation is done until all its inputs, for that same block, have been computed.
http://crca.ucsd.edu/~msp/techniques/latest/book-html/node120.html
Now much like fanning message connections this ordering can become ambigous if non-local signal connections are involved:
[noise~] | [s~ X]
[r~ X] | [lop~ 5] |
Now just tell from looking, which signal-block of [noise~] the [lop~ 5] will filter: the current one or the previous one? You can't tell, just as you cannot tell the result of this addition by just looking:
[1(
|
|
[+ ]
|
1 or 2?
The message solution is a trigger:
[1( | [t a a] | / [+ ] | 2
The signal solution are two sub-patches:
[pd noise] ==> [noise~] | | | [s~ X] [outlet~] <- dummy! | [pd lop_5] ==> [inlet~] <- dummy!
[r~ X]
|
[lop~ 5]
Because there is a dummy-signal connection, now the ordering is well-defined again through the signal-connection: The upper subpatch will be calculated first, so the lop~ will filter the current block - often this would not matter, though.
But now this explicit ordering breaks horribly if you create a dsp-loop. That is, if you put a [r~ Y] in the upper and a [s~ Y] in the lower subpatch. Pd will warn you about this with its "DSP-loop detected" error message.
I hope this will make the issue a bit clearer, again I would recommend to study these two pages closely: http://crca.ucsd.edu/~msp/techniques/latest/book-html/node120.html http://crca.ucsd.edu/~msp/techniques/latest/book-html/node121.html
Frank Barknecht _ ______footils.org_ __goto10.org__
Hi Frank,
and thanks for all that! I'll make sure it goes into every tutorial I ever write ever again ;-)
But actually, what I was referring to was this problem of--for example--having a feedback system where the send~ is inside a subpatch and the receive~ is outside of it. IIRC, you have to be very careful about whether you create the send~ subpatch first or the receive~ first. One way gave me a DSP loop and the other way didn't, and I couldn't figure out why it would work like that at all. Maybe I'll have to sit down and make an example of what I mean, or you could try it for yourself and see. This problem made me totally crazy while trying to make a feedback-modulated AM/FM synth several months ago.
best, d.
Hallo, Derek Holzer hat gesagt: // Derek Holzer wrote:
and thanks for all that! I'll make sure it goes into every tutorial I ever write ever again ;-)
But actually, what I was referring to was this problem of--for example--having a feedback system where the send~ is inside a subpatch and the receive~ is outside of it. IIRC, you have to be very careful about whether you create the send~ subpatch first or the receive~ first.
Just remember, that everything, that is connected directly trough signal cords, will be evaluated top to bottom, and everything that is not connected through signal chords, will be evaluated in "random" order, but it can be made to appear to be connected with signal cords by putting it into subpatches, even if these subpatches are just connected with dummy in/outlet~s.
One way gave me a DSP loop and the other way didn't, and I couldn't figure out why it would work like that at all. Maybe I'll have to sit down and make an example of what I mean, or you could try it for yourself and see. This problem made me totally crazy while trying to make a feedback-modulated AM/FM synth several months ago.
For feedback stuff you will always have one block delay. So the goal should be to get the smallest block size possible/necessary, and you do that by re-block~ing a *single* subpatch. Inside of this subpatch one should put only the objects necessary, nothing more, to save CPU cycles. You may forget about the [pd write]---[pd read] stuff as soon as feedback is involved, it won't help anyway.
Frank Barknecht _ ______footils.org_ __goto10.org__
Hei,
Thanks for this info.
On 10/02/2007, at 0.51, Frank Barknecht wrote:
Derek Holzer hat gesagt: // Derek Holzer wrote:
But actually, what I was referring to was this problem of--for example--having a feedback system where the send~ is inside a
subpatch and the receive~ is outside of it. IIRC, you have to be very careful about whether you create the send~ subpatch first or the receive~
first.Just remember, that everything, that is connected directly trough signal cords, will be evaluated top to bottom, and everything that is not connected through signal chords, will be evaluated in "random" order [...]
But it properly isn't random, as from the quote from Millers book
says "in reality Pd executes them all in a sequential order". The
lesson learned from here, from Frank, is, as i understand it, that if
the order is not directly defined via cords, then one can't be sure
to know what happens. But as with the adding example with out the
trigger, one can be lucky to make it work as wanted without the
tricker. The same may have happened for Derek in this send~/receive~
case.
As in: the 'in reality sequential order' might be from line one to
EOF, but if cords/connections have been made to directly specify an
execution order, they'll be followed first. As in a hierarchy of
execution order.
Just a thought. - I haven't read the code.
Hallo, Steffen hat gesagt: // Steffen wrote:
On 10/02/2007, at 0.51, Frank Barknecht wrote:
Just remember, that everything, that is connected directly trough signal cords, will be evaluated top to bottom, and everything that is not connected through signal chords, will be evaluated in "random" order [...]
But it properly isn't random, as from the quote from Millers book
says "in reality Pd executes them all in a sequential order". The
lesson learned from here, from Frank, is, as i understand it, that if
the order is not directly defined via cords, then one can't be sure
to know what happens.
Yep, exactly.
Of course, not much in a computer is truly random, but from a patch author's and user's point of view, in the end the order of executing non-local connections appears "random". If you look at a patch you built one week ago, do you remember the order you made the connections? And maybe you copied and pasted some stuff, used Ctrl-Z or something else, which may have changed the order without you knowing it.
That's why I really prefer to call this "random" or "undefined" or "ambigous" in a non-scientific, practical sense. It may work now, but may break tomorrow.
Also one should be aware, that very often the actual order of execution of signal cords doesn't matter. It does matter in waveguide stuff or in comb filters where you need these small delay times.
Frank Barknecht _ ______footils.org_ __goto10.org__
This is a great explanation! It makes total sense now.
~Kyle
On 2/9/07, Frank Barknecht fbar@footils.org wrote:
Hallo, Derek Holzer hat gesagt: // Derek Holzer wrote:
But it is true that creation order affects this? Can you explain how, since I could never quite get it worked out properly and it cost me many hours and maybe even a few gray hairs ;-)
It's similar to normal messages, just replace [trigger] with [pd x] if you want explicit ordering.
Whereas in the message world, unknown ordering of "fanned" connections is the problem, that is solved with [trigger ...], in the signal world, non-local connections like s~, throw~ or delwrite~ are possible culprits that may introduce block-sized delays.
The basic problem is, that not all dsp-objects are calulated at the same time. They are calculated in the same block of samples, but if you have two signal objects one has to be calculated before the other.
This ordering is easy if you have direct connections:
[noise~] | [lop~ 5] |
[noise~ 1] will be calculated first, then [lop~ 5] can filter the result as input.
Or as Miller puts it:
Although the tilde objects in a patch may have a complicated topology of audio connections, in reality Pd executes them all in a sequential order, one after the other, to compute each block of audio output. This linear order is guaranteed to be compatible with the audio interconnections, in the sense that no tilde object's computation is done until all its inputs, for that same block, have been computed.
http://crca.ucsd.edu/~msp/techniques/latest/book-html/node120.html
Now much like fanning message connections this ordering can become ambigous if non-local signal connections are involved:
[noise~] | [s~ X]
[r~ X] | [lop~ 5] |
Now just tell from looking, which signal-block of [noise~] the [lop~ 5] will filter: the current one or the previous one? You can't tell, just as you cannot tell the result of this addition by just looking:
[1( |
|
[+ ] | 1 or 2?The message solution is a trigger:
[1( | [t a a] | / [+ ] | 2
The signal solution are two sub-patches:
[pd noise] ==> [noise~] | | | [s~ X] [outlet~] <- dummy! | [pd lop_5] ==> [inlet~] <- dummy!
[r~ X] | [lop~ 5]
Because there is a dummy-signal connection, now the ordering is well-defined again through the signal-connection: The upper subpatch will be calculated first, so the lop~ will filter the current block - often this would not matter, though.
But now this explicit ordering breaks horribly if you create a dsp-loop. That is, if you put a [r~ Y] in the upper and a [s~ Y] in the lower subpatch. Pd will warn you about this with its "DSP-loop detected" error message.
I hope this will make the issue a bit clearer, again I would recommend to study these two pages closely: http://crca.ucsd.edu/~msp/techniques/latest/book-html/node120.html http://crca.ucsd.edu/~msp/techniques/latest/book-html/node121.html
Ciao
Frank Barknecht _ ______footils.org_ __goto10.org__
PD-list@iem.at mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
Thanks guys. I guess this serves as an example of how not to fall into this trap . The explanation you gave is worth the misery I went through chasing this, hopefully one for the archives if someone else hits the same issue.
I wonder, about debug. Is there any useful way of using either -d<n> (--debug) or find-last-error to help tracing these little nasties? In other words can Pd show how it is trying to evaluate the tree?
Best,
ANdy
On Fri, 9 Feb 2007 16:21:00 +0000 padawan12 padawan12@obiwannabe.co.uk wrote:
I found this behaviour slightly surprising, but on reflection it makes sense. Pd doesn't seem to check deeply into subpatches when looking for DSP feedback loops.
I started making a simple waveguide synth and decided, for a change, to work on the feedback mechanism inside another subpatch. I kept getting DSP loop error even though the signal path contains a [s~] and unique matching [r~]. Making the feedback loop require a [send~] and [receive~] in the outermost block seems to defeat the use of smaller blocksizes in subpatches.
Anyone care to comment on this (attached example). Or am I understanding this incorrectly?
Cheers. Andy