Hi smart pd-dev people, please help me. I'm miserably failing in designing new externals with the amazing new multi-channel feature.
Getting inspired by some of the MAX objects, for fun and for starters I thought I'd clonen [mc.list~], which is kinda like the new [pack~] but you can set the values as arguments. It would also allow us to use the list box to set all values.
My first and only 'mc' external so far is [nchs~], see --> https://github.com/porres/pd-else/blob/master/Classes/Source/nchs~.c I already mentioned it and said it'd be cool to have it in Vanilla. It outputs a float value but I wanted, as a first step, to adapt it to output a signal value instead, but I can't do not even that, let alone have a new external that outputs a multichannel signal. From the [nchs~] code, I just use the 'dsp method' to get 'sp[0]->s_nchans' (number of channels) and call a bang function that outputs the float.
If I create a 'perform' method to get number of channels as a signal, Pd blows up, and I don't know what I'm doing wrong as I'm doing what I do with every other regular external. Not that I wanted a signal output, I'd rather have the float output, but I expected this to work and I can't see the problem. I am assuming multichannel externals are different and I don't really know the secret or the recipe yet to mess with them. Check code below.
*static* t_int *nchs_perform(t_int *w){
t_check *x = (t_check *)(w[1]);
*int* n = (t_int)(w[2]);
t_sample *in = (t_sample *)(w[3]);
t_sample *out = (t_sample *)(w[4]);
*while*(n--)
*out = x->x_nchans;
*return*(w+5);
}
*static* *void* nchs_tilde_dsp(t_check *x, t_signal **sp){
x->x_nchans = sp[0]->s_nchans;
dsp_add(check_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); }
I can't imagine the further challenges to output or treat multichannel signals, but I'd like to start by clarifying this.
funny enough, [pack~]/[unpack~] do not have 'perform' methods so I can't figure this out.
Thanks a lot. cheers~
On 1/23/23 16:18, Alexandre Torres Porres wrote:
*static* *void* nchs_tilde_dsp(t_check *x, t_signal **sp){
x->x_nchans = sp[0]->s_nchans; dsp_add(check_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec);
}
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
see the example (mostly: pack~)
gfmdas IOhannes
Em seg., 23 de jan. de 2023 às 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function. Anyway, just having quite a hard time figuring out how to have such a routine. I had seen [send~] too, and it's able to call a 'perform' routine but I couldn't figure it out as well what I was doing wrong in [nchs~].
I bet I'm missing lots of details and would need some sort of dummies tutorial, step by step, to learn how to make simple objects like [mc.list~] :/
cheers
gfmdas IOhannes _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
On 1/24/23 04:54, Alexandre Torres Porres wrote:
Em seg., 23 de jan. de 2023 às 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
yes. with all multichannel aware externals. how would Pd know the fixed number of outputs, if you don't tell it?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function.
the interesting part is the "dsp" method. you cannot change the number of output signals in the perform routine (that is: every tick). but you can change (or rather: must set) it when the DSP-graph is created, thus in the "dsp" method.
mgfdsrfad IOhannes
OK, just now changed this - there's a one-channel signal created for all signal outputs. Now if you want more than one channel you have to call signal_swapforchans() (see d_arithmentic for example).
cheers M
On Tue, Jan 24, 2023 at 08:07:22AM +0100, IOhannes m zmoelnig wrote:
On 1/24/23 04:54, Alexandre Torres Porres wrote:
Em seg., 23 de jan. de 2023 Ã s 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
yes. with all multichannel aware externals. how would Pd know the fixed number of outputs, if you don't tell it?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function.
the interesting part is the "dsp" method. you cannot change the number of output signals in the perform routine (that is: every tick). but you can change (or rather: must set) it when the DSP-graph is created, thus in the "dsp" method.
mgfdsrfad IOhannes
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Cool!
I don't see these changes yet. Did you forget to push them or are you still working on it?
(I am working on some clone multi-channel bugfixes and I would need the new signal_swapforchans() function :-)
Christof
On 25.01.2023 05:46, Miller Puckette via Pd-dev wrote:
OK, just now changed this - there's a one-channel signal created for all signal outputs. Now if you want more than one channel you have to call signal_swapforchans() (see d_arithmentic for example).
cheers M
On Tue, Jan 24, 2023 at 08:07:22AM +0100, IOhannes m zmoelnig wrote:
On 1/24/23 04:54, Alexandre Torres Porres wrote:
Em seg., 23 de jan. de 2023 às 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
yes. with all multichannel aware externals. how would Pd know the fixed number of outputs, if you don't tell it?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function.
the interesting part is the "dsp" method. you cannot change the number of output signals in the perform routine (that is: every tick). but you can change (or rather: must set) it when the DSP-graph is created, thus in the "dsp" method.
mgfdsrfad IOhannes
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
I think I hadn't pushed them, oops. And now I'm thinking again - maybe it's more elegant yet to provide empty output signals (channels=length=vec=0) and instead of (for example) sp[2] = signal_swapforchans(sp[2], outchans); you'd just write signal_setchans(sp[2], ouchans).
cheers Miller
On Wed, Jan 25, 2023 at 03:42:15PM +0100, Christof Ressi wrote:
Cool!
I don't see these changes yet. Did you forget to push them or are you still working on it?
(I am working on some clone multi-channel bugfixes and I would need the new signal_swapforchans() function :-)
Christof
On 25.01.2023 05:46, Miller Puckette via Pd-dev wrote:
OK, just now changed this - there's a one-channel signal created for all signal outputs. Now if you want more than one channel you have to call signal_swapforchans() (see d_arithmentic for example).
cheers M
On Tue, Jan 24, 2023 at 08:07:22AM +0100, IOhannes m zmoelnig wrote:
On 1/24/23 04:54, Alexandre Torres Porres wrote:
Em seg., 23 de jan. de 2023 Ã s 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
yes. with all multichannel aware externals. how would Pd know the fixed number of outputs, if you don't tell it?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function.
the interesting part is the "dsp" method. you cannot change the number of output signals in the perform routine (that is: every tick). but you can change (or rather: must set) it when the DSP-graph is created, thus in the "dsp" method.
mgfdsrfad IOhannes
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
you'd just write signal_setchans(sp[2], ouchans).
That's what I had originally suggested, but you rightfully pointed out that changing the channel number in place can be problematic if signals are reused...
So it would have to be at least:
sp[2] = signal_setchans(sp[2], outchans);
empty output signals (channels=length=vec=0)
But then what is the point of having the signal if it does not provide any information?
Christof
On 25.01.2023 17:09, Miller Puckette wrote:
I think I hadn't pushed them, oops. And now I'm thinking again - maybe it's more elegant yet to provide empty output signals (channels=length=vec=0) and instead of (for example) sp[2] = signal_swapforchans(sp[2], outchans); you'd just write signal_setchans(sp[2], ouchans).
cheers Miller
On Wed, Jan 25, 2023 at 03:42:15PM +0100, Christof Ressi wrote:
Cool!
I don't see these changes yet. Did you forget to push them or are you still working on it?
(I am working on some clone multi-channel bugfixes and I would need the new signal_swapforchans() function :-)
Christof
On 25.01.2023 05:46, Miller Puckette via Pd-dev wrote:
OK, just now changed this - there's a one-channel signal created for all signal outputs. Now if you want more than one channel you have to call signal_swapforchans() (see d_arithmentic for example).
cheers M
On Tue, Jan 24, 2023 at 08:07:22AM +0100, IOhannes m zmoelnig wrote:
On 1/24/23 04:54, Alexandre Torres Porres wrote:
Em seg., 23 de jan. de 2023 às 14:34, IOhannes m zmoelnig zmoelnig@iem.at escreveu:
multichannel objects must create the output signals themselves. (as the object might change the number of channels).
even with [nchs~] where I'd have a fixed number of inputs/outputs?
yes. with all multichannel aware externals. how would Pd know the fixed number of outputs, if you don't tell it?
see the example (mostly: pack~)
I saw it and it's quite simple, withou a 'perform' routine it uses a copy function.
the interesting part is the "dsp" method. you cannot change the number of output signals in the perform routine (that is: every tick). but you can change (or rather: must set) it when the DSP-graph is created, thus in the "dsp" method.
mgfdsrfad IOhannes
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
Pd-dev mailing list Pd-dev@lists.iem.at https://urldefense.com/v3/__https://lists.puredata.info/listinfo/pd-dev__;!!...
On Wed, Jan 25, 2023 at 05:22:14PM +0100, Christof Ressi wrote:
you'd just write signal_setchans(sp[2], ouchans).
That's what I had originally suggested, but you rightfully pointed out that changing the channel number in place can be problematic if signals are reused...
So it would have to be at least:
sp[2] = signal_setchans(sp[2], outchans);
empty output signals (channels=length=vec=0)
But then what is the point of having the signal if it does not provide any information?
you need it to know the length and sample rate (what nullsignal used to do :)
On 1/25/23 17:09, Miller Puckette via Pd-dev wrote:
I think I hadn't pushed them, oops. And now I'm thinking again - maybe it's more elegant yet to provide empty output signals (channels=length=vec=0)
conceptually, i like this; though i would suggest "channels=0; length=64" (or whatever).
and instead of (for example) sp[2] = signal_swapforchans(sp[2], outchans); you'd just write signal_setchans(sp[2], ouchans).
hmm, wouldn't that modify the t_signal* struct that sp[2] points to, potentially breaking the reuse? (so it ought to be "signal_setchans(&sp[2], outchans)")
and i find the "swapforchans" slightly confusing (which fo(u)r channels are being swapped? the actual swapping is done by re-assigning a new value to sp[2]). so how about: sp[2] = signal_makemultichannels(sp[2], outchans);
gfmasdr IOhannes
On Wed, Jan 25, 2023 at 05:34:48PM +0100, IOhannes m zmoelnig wrote:
conceptually, i like this; though i would suggest "channels=0; length=64" (or whatever).
yep - and in fact I need length to be correct, otherwise there's no easy way to get it.
and instead of (for example) sp[2] = signal_swapforchans(sp[2], outchans); you'd just write signal_setchans(sp[2], ouchans).
hmm, wouldn't that modify the t_signal* struct that sp[2] points to, potentially breaking the reuse? (so it ought to be "signal_setchans(&sp[2], outchans)")
I _think_ it works just to pass sp[2] in place - it's a (t_signal *) and all that's needed is to alter member element s_vec, s_nchans.
and i find the "swapforchans" slightly confusing (which fo(u)r channels are being swapped? the actual swapping is done by re-assigning a new value to sp[2]). so how about: sp[2] = signal_makemultichannels(sp[2], outchans);
so this would become moot.
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
The implementation of signal_setoutchans() looks good to me! There is indeed no danger of breaking signal aliasing. Since the dummy output signals are "empty" (s_nchans = 0), they are allocated from the "borrow" free list and not from the "real" free list. Nice :-)
I think signal_setoutchans() is quite elegant and pleasant to use. Thanks!
Christof
On 25.01.2023 18:04, info@christofressi.com wrote:
yep - and in fact I need length to be correct, otherwise there's no
easy way to get it.
That's what I was hinting at :-)
I find the empty signal quite elegant. Only s_nchans and s_vec are 0, the rest stays intact. This makes sense conceptionally because s_nchans * s_length is still 0.
sp[2] = signal_makemultichannels(sp[2], outchans);
I like this! I think the naming is very descriptive.
Christof
Am 25.01.2023 17:39 schrieb Miller Puckette via Pd-dev pd-dev@lists.iem.at:
On Wed, Jan 25, 2023 at 05:34:48PM +0100, IOhannes m zmoelnig wrote: > conceptually, i like this; though i would suggest "channels=0; length=64" > (or whatever). > yep - and in fact I need length to be correct, otherwise there's no easy way to get it. > > and instead of (for example) > > sp[2] = signal_swapforchans(sp[2], outchans); > > you'd just write > > signal_setchans(sp[2], ouchans). > > hmm, wouldn't that modify the t_signal* struct that sp[2] points to, > potentially breaking the reuse? (so it ought to be "signal_setchans(&sp[2], > outchans)") > I _think_ it works just to pass sp[2] in place - it's a (t_signal *) and all that's needed is to alter member element s_vec, s_nchans. > and i find the "swapforchans" slightly confusing (which fo(u)r channels are > being swapped? the actual swapping is done by re-assigning a new value to > sp[2]). > so how about: > sp[2] = signal_makemultichannels(sp[2], outchans); > so this would become moot. > > _______________________________________________ > Pd-dev mailing list > Pd-dev@lists.iem.at > https://lists.puredata.info/listinfo/pd-dev _______________________________________________ Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev