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

Nick Porcaro nick at ccrma.stanford.edu
Thu Sep 12 12:09:19 CEST 2019


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> wrote:
> 
> Hi Miller-
> 
>> On Aug 20, 2019, at 7:08 PM, Miller Puckette <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
>>> https://lists.puredata.info/listinfo/pd-dev
>> 
>> 
>> 
>> 
>> _______________________________________________
>> Pd-dev mailing list
>> Pd-dev at lists.iem.at
>> https://lists.puredata.info/listinfo/pd-dev
>> 
>> 
> 
> 
> 
> 

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


More information about the Pd-dev mailing list