[PD-dev] dynamic patching - is iemguts the way to go?

Nick Porcaro nick at ccrma.Stanford.EDU
Fri Sep 13 01:29:37 CEST 2019


To be more clear the answer was basically this:

My original thought was this (which of course every reasonable person would assume ;-))

foreach enabled patch in the fx chain: 
    tick this patch
end

But this could not work because “tick this patch” is something like this:

pd->processFloat (1, pdInBuffer.getData(), pdOutBuffer.getData());

Which has no reference to any patch, now does it? ;-)

So this is what you have to do:

foreach enabled patch in the fx chain: 
    disable other patches 
    tick this patch
   reenable other patches
end


- Nick



> On Sep 12, 2019, at 6:36 PM, Nick Porcaro <nick at ccrma.Stanford.EDU> wrote:
> 
> OK folks all is well now - the solution to the problem is as I expected.
> 
> As Miller said, pdlib ticks all the patches in question so if you just want to feed
> samples from one patch to another you have to make sure all the other patches
> are switched off.  
> 
> I had deceived myself by disabling them at a different level in my code.
> 
> Whew, that was close!
> 
> - Nick
> 
>> On Sep 12, 2019, at 6:09 AM, Nick Porcaro <nick at ccrma.Stanford.EDU <mailto:nick at ccrma.Stanford.EDU>> wrote:
>> 
>> Miller, et. al:
>> 
>> 
>> I think I see the problem, this code would appear to tick ALL the patches
>> in the pd instance:
>> 
>> for (each buffer from the audio callback) {
>>     for (a smaller buffer that’s the pd block size (eg 64)) {
>>         pd->processFloat (oneTick, smallBufferIn, smallBufferOut);
>>   }
>> }
>> 
>> 
>> So maybe it should be like this:
>> 
>> 
>> for (each buffer from the audio callback) {
>>     for (a smaller buffer that’s the pd block size (eg 64)) {
>>         // Do something here to disable the patches that are not active
>>         // eg :
>>         for (patches that are not this one) {
>>             pd->sendFloat(“/patchName/enable",0);
>>         }
>>         pd->processFloat (oneTick, smallBufferIn, smallBufferOut);
>>     }
>> }
>> 
>> The code above is a member function of a C++ class that encapsulates a patch.
>> I just realized as I was falling asleep for the night that this line is NOT specific
>> to any patch!
>> 
>>         pd->processFloat (oneTick, smallBufferIn, smallBufferOut);
>> 
>> I’ll try something first thing tomorrow and I’ll let you all know what happens.
>> 
>> 
>> - Nick
>> 
>>> On Sep 12, 2019, at 4:56 AM, Nick Porcaro <nick at ccrma.Stanford.EDU <mailto:nick at ccrma.Stanford.EDU>> wrote:
>>> 
>>> Hi Miller-
>>> 
>>>> On Aug 20, 2019, at 7:08 PM, Miller Puckette <msp at ucsd.edu <mailto:msp at ucsd.edu>> wrote:
>>>> 
>>>> actually I wrote that before I thought the whole thing out :)
>>>> 
>>>> No, if you "tick" a pdlib instance you tick all the patches in it - so teh
>>>> way to get different patches in different orders is to call up a separate
>>>> Pd instance for each of them, and use "adc~" and "dac~" objects to get
>>>> audio in and out - that incurs zero latency (once you've buffered 64
>>>> samples in the first place).
>>> 
>>> I tried this two ways:  
>>> 
>>> - Create separate Pd  instances for each patch wrapped in adc~ and dac~
>>> 
>>> - Use a single Pd  instance with multiple patches,  with each patch wrapped in adc~ and dac~
>>> 
>>> Then I have a simple JUCE app (based on the sampler example) that drives
>>> these pd patches.
>>> 
>>> There is no problem with doing switch~ and such, but I am 
>>> getting distortion that seems like clipping in both cases (one pd instance with many patches
>>> or multiple pd instances with one patch)
>>> 
>>> To be more clear these wrapper patches are like:
>>> 
>>> Patch 1:     [adc~]   ->   [lop~ 200] -> [dac~]
>>> Patch 2:     [adc~]   ->   [hip~ 200] -> [dac~]
>>> 
>>> These wrapper patches also have a loadbang to pd dsp 1;
>>> 
>>> Then the code that calls these patches does something like this calling libpd:
>>> 
>>> for (each buffer from the audio callback) {
>>>     for (a smaller buffer that’s the pd block size (eg 64)) {
>>>         pd->processFloat (oneTick, smallBufferIn, smallBufferOut);
>>>   }
>>> }
>>> 
>>> I tried scaling the input and output to these  wrapper patches after the adc~ and before the dac~
>>> and that does not solve the distortion/clipping problem either.
>>> 
>>> There are a couple of more things I can try:
>>> 
>>>    - make the wrapper patches even simpler, just scaling instead of the filters.
>>>    - dump the samples to a file and maybe that will shed some light on the problem.
>>>    - making a much simpler example program that I can share will you all.
>>> 
>>> I have libpd and pd source directly compiled into my example
>>> 
>>> Any other ideas would be greatly appreciated!
>>> 
>>> 
>>>> 
>>>> OR, within one pd instance, in libpd or in Pd, you can use switch~ objects,
>>>> switched off, to control each sub-patch.  Send the switch~ objects bangs in
>>>> whatever orders you wish.  In this scenario, tabsend~ and tabreceive~ would
>>>> be the simplemt way to pass signals between them.  In libpd you can do this
>>>> zero-latency (just stuff your inpuits into arrays before sending all the
>>>> tick messages and copy the results out afterward).
>>> 
>>> This approach works well, but the problem is I can’t insert non-Pd signal processing
>>> anywhere I’d like in the Pd patch so that’s why I went with the first approach.
>>> 
>>>> 
>>>> Within the Pd app, you can do teh same thing but you incur one tick extra
>>>> latency, because copying the autio into the tables has to happen on the
>>>> previous tick form the one on which you get the outputs back.
>>>> 
>>>> If you like danger, you can write an external tilde object that, for its
>>>> "dsp" action, sends a message to teh patch that can "tick" the switch~
>>>> objects right in the middle of Pd/s DSP tick.  This is not part of Pd
>>>> because it could cause major confusion if general-purpose Pd messages
>>>> got sent around in mid-tick.
>>>> 
>>>> cheers
>>>> Miller
>>>> 
>>>> On Tue, Aug 20, 2019 at 11:55:58PM +0200, Roman Haefeli wrote:
>>>>> On Tue, 2019-08-20 at 12:09 -0700, Miller Puckette wrote:
>>>>>> I think the way to do this in libpd is to open them all as separate
>>>>>> patches
>>>>>> within one instance of Pd (so that symbols are shared) and use
>>>>>> "tabsend"
>>>>>> and "tabreceive" to route signals to/from them, using shared names
>>>>>> like
>>>>>> "channel1" as both inputs and outputs so you can rearrange them in
>>>>>> any
>>>>>> order.
>>>>>> 
>>>>>> (Beware of allowing patches to _write_ andy of their output channels
>>>>>> before
>>>>>> reading all the input channels, if you're re-using the same channels
>>>>>> as 
>>>>>> inputs and outputs :)
>>>>> 
>>>>> Do I understand right: When loading them as separate patches, you can
>>>>> dynamically re-order the signal flow by using [tabsend~]/[tabreceive~]
>>>>> (which you could with abstractions, too) _without_ adding latency?
>>>>> 
>>>>> And: When changing the symbol of [tabsend~] or [tabreceive~], is the
>>>>> DSP graph re-calculated?
>>>>> 
>>>>> Roman
>>>> 
>>>> 
>>>> 
>>>>> _______________________________________________
>>>>> Pd-dev mailing list
>>>>> Pd-dev at lists.iem.at <mailto:Pd-dev at lists.iem.at>
>>>>> https://lists.puredata.info/listinfo/pd-dev <https://lists.puredata.info/listinfo/pd-dev>
>>>> 
>>>> 
>>>> 
>>>> 
>>>> _______________________________________________
>>>> Pd-dev mailing list
>>>> Pd-dev at lists.iem.at <mailto:Pd-dev at lists.iem.at>
>>>> https://lists.puredata.info/listinfo/pd-dev <https://lists.puredata.info/listinfo/pd-dev>
>>>> 
>>>> 
>>> 
>>> 
>>> 
>>> 
>> 
> 

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.puredata.info/pipermail/pd-dev/attachments/20190912/43b2cf6d/attachment.html>


More information about the Pd-dev mailing list