[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