• ### Multiple signal outlets in external

Hi! I'm new writing externals, so sorry about the newbie question.

I would like to create a multichannel object, with several outlets but I'm having problems when adding more than 2. The first 2 outlets do what they have to do but the others doesn't behave as they should. At this point I'm asking myself, is possible to have more than 2 signal outlets? And if so, do they have to be defined in a different way than the others?

• Posts 11 | Views 3325
• @justAndrea Just to give you confidence in the possibility..... yes, there are existing objects with many outputs possible........ like [matrix~] for which I know you can have at least 64 with that creation argument given.
But I have no experience of writing externals......
David.

• Hi Andrea,

As @whale-av has pointed out, it's most certainly possible to create abstractions or externals with more than 2 signal outlets. If you are having issues then the problem very likely lays somewhere else. Would you care to share your patch/code here?

Cheers!
Gilberto

• Hi,
Thanks both for answering! I'm just trying to make this work...

It works correctly for the first two outlets, but the outlet 3 returns inlet2, and the outlet4 returns inlet1, so I guess that I'm not declaring something correctly...

``````t_int *ext_perform(t_int *w)
{
int i;
t_pan *x = (t_pan *)(w[1]);
t_sample  *in1 = (t_sample *)(w[2]);
t_sample  *in2 = (t_sample *)(w[3]);
t_sample  *in3 = (t_sample *)(w[4]);
t_sample  *in4 = (t_sample *)(w[5]);
t_sample  *out1 = (t_sample *)(w[6]);
t_sample  *out2 = (t_sample *)(w[7]);
t_sample  *out3 = (t_sample *)(w[8]);
t_sample  *out4 = (t_sample *)(w[9]);
int          n = (int)(w[10]);

for (i = 0; i < n; i++) {
*out1++ = *in1++;
*out2++ = *in2++;
*out3++ = *in3++;
*out4++ = *in4++;
}
return (w+11);
}`````````
• @justAndrea can you post your dsp method and the new routine? It could be that there is something wrong there.

• Here you have. Thanks!

``````void ext_dsp(t_pan *x, t_signal **sp)
{
sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[0]->s_n);

}

void *ext_new(t_floatarg f)
{
t_pan *x = (t_pan *)pd_new(pan_class);

x->x_in2 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_in3 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_in4 = inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
x->x_out1 = outlet_new(&x->x_obj, &s_signal);
x->x_out2 = outlet_new(&x->x_obj, &s_signal);
x->x_out3 = outlet_new(&x->x_obj, &s_signal);
x->x_out4 = outlet_new(&x->x_obj, &s_signal);
return (void *)x;
}`````````
• Don't know if it really has something to do, but here's how I create signal inlets:
`inlet_new(&x->obj, &x->obj.ob_pd, gensym("signal"), gensym("signal"));`
and this is how I create signal outlets:
`inlet_new(&x->obj, &x->obj.ob_pd, gensym("signal"), gensym("signal"));`
I don't assign the inlets or outlets to any element of the object's data structure.
Since you use an argument in your new routine, I guess you want to use that to create as many outlets, right? You could probably do:
`for(i = 0; i < f; i++) outlet_new(&x->obj, gensym("signal"));`
I've used that in an external (with a hard-coded number of loop iterations, no argument) I've written and it does create four outlets without a problem.

And lastly, why do you return the pointer to the object with a cast to `void`? Shouldn't you just return x there? Also not sure if this has anything to do with your problem. I'm just comparing your code to code I've written for externals that works. Not a C guru...

• Hi @alexandros, thanks for your answer. Actually I do create the outlets, but they don't behave correctly. They should work like this:

Inlet1-outlet1
Inlet2-outlet2
Inlet3-outlet3
Inlet4-outlet4

Inlet1-outlet1
Inlet2-outlet2
Inlet2-outlet3
Inlet1-outlet4

After debugging I saw that I get correctly the data from the inlets and that I can also assign other values to the outlets, and it works correctly. The problem is when sending the signals from the inlets to the outlets, so the assignation `*out3++ = *in3++; *out4++ = *in4++;`

And regarding the cast to void...I'm just playing around with the code provided in How to write an external in PD and I didn't change it so much.

• I think the problem comes from the fact that the input signals and output signals can use the same vectors. This is called "in-place" processing and is useful to optimize the DSP chain. For example [noise~] -> [*~ 0.3] -> [dac~ 1], should use only one vector. Depending on the connections between the objects, it's possible that the outlet 3 corresponds to the inlet 2 and the outlet 4 to the inlet 1.
In the dsp method you can post the address of the vectors to check this. The solution is to copy the input vectors in other temporary vectors and thereafter write the content of the temporary vectors in the output vectors.

@alexandros, the function returns void so the cast is valid even if it's pretty useless.

At last : You should always prefer to use the static symbols like s_signal, s_bang, etc. it's much more optimized. And there is the "signalinlet_new" method that you could use instead of "inlet_new".

• You can have a look at the source code and the binaries.

• Wow, thank you so much @PierreGuillot!! Great explanation

Posts 11 | Views 3325
Internal error.

Oops! Looks like something went wrong!