I'm trying to create a signal external with a variable number of inlets and outlets. As a test, I have written an object that copies its input to the respective output. When I put the object in a subpatch and use [block~] to change the block size, it crashes. Loading Pd with gdb gives the following output, which to me doesn't seem very helpful:
``` Program received signal SIGSEGV, Segmentation fault. 0x0000000000000000 in ?? () ```
Here's the code of the object (the var_io_tilde_process function is there as a test to see if I can process the output in a routine other than the perform one):
```
#include <m_pd.h>
static t_class *var_io_tilde_class;
typedef struct _var_io_tilde { t_object obj; t_sample f; t_sample **in; t_sample **out; t_sample *buf; int chnls; int blksize; int bufbytes; } t_var_io_tilde;
static void var_io_tilde_process(t_var_io_tilde *x, int n) { int i, j; t_sample **out = x->out; t_sample *buf = x->buf; for (i = 0; i < x->chnls; i++) { for (j = 0; j < n; j++) { out[i][j] = buf[i*n+j]; } } }
t_int *var_io_tilde_perform(t_int *w) { int i, j, n; t_var_io_tilde *x = (t_var_io_tilde *)(w[1]); n = (int)(w[2]); t_sample **in = x->in; //t_sample **out = x->out; t_sample *buf = x->buf;
for (i = 0; i < x->chnls; i++) { for (j = 0; j < n; j++) { buf[i*n+j] = in[i][j]; } } var_io_tilde_process(x, n); return (w+3); }
void var_io_tilde_dsp(t_var_io_tilde *x, t_signal **sp) { int i; int bufbytes = x->bufbytes; t_sample **dummy = x->in; for (i=0; i<x->chnls; i++) *dummy++ = sp[i]->s_vec; dummy = x->out; for (i=x->chnls; i<x->chnls*2; i++) *dummy++ = sp[i]->s_vec;
if (x->blksize != sp[0]->s_n) { x->blksize = sp[0]->s_n; x->bufbytes = x->chnls*2*sp[0]->s_n; x->buf = (t_sample *)resizebytes((void *)x->buf, bufbytes, x->bufbytes); if (x->buf == NULL) { pd_error(x, "cannot realloc %d bytes of memory", x->bufbytes); return; } } dsp_add(var_io_tilde_perform, 2, x, sp[0]->s_n); }
void *var_io_tilde_new(t_floatarg f) { int i; t_var_io_tilde *x = (t_var_io_tilde *)pd_new(var_io_tilde_class); x->chnls = (f) ? f : 2; x->blksize = sys_getblksize();
/* create signal inlets (first is done in var_io_tilde_setup) */ for (i=1; i<x->chnls; i++) inlet_new(&x->obj, &x->obj.ob_pd, &s_signal, &s_signal); /* create signal outlets */ for (i=0; i<x->chnls; i++) outlet_new(&x->obj, &s_signal);
x->in = (t_sample **)getbytes(x->chnls * sizeof(t_sample **)); x->out = (t_sample **)getbytes(x->chnls * sizeof(t_sample **));
for (i=0; i<x->chnls; i++) x->in[i] = x->out[i] = 0;
x->bufbytes = x->chnls*2*x->blksize; x->buf = (t_sample *)getbytes(x->bufbytes * sizeof(t_sample *)); return (void *)x; }
void var_io_tilde_free(t_var_io_tilde *x) { freebytes(x->in, sizeof(x->in)); freebytes(x->out, sizeof(x->out)); }
void var_io_tilde_setup(void) { var_io_tilde_class = class_new(gensym("var_io~"), (t_newmethod)var_io_tilde_new, (t_method)var_io_tilde_free, sizeof(t_var_io_tilde), CLASS_DEFAULT, A_DEFFLOAT, 0); class_addmethod(var_io_tilde_class, (t_method)var_io_tilde_dsp, gensym("dsp"), 0); CLASS_MAINSIGNALIN(var_io_tilde_class, t_var_io_tilde, f); }
```
What am I doing wrong? And, if this is not the way, how can I create an object with a variable number of inlets and outlets (preferably independent of one another).
what is this "2" supposed to represent?
This looks like a mistake to me. The buffer certainly does not have to be twice as large, as it is only used to copy the input.
To solve the mystery, you don't allocate the right amount of memory because you forgot about the element type:
x->bufbytes = x->chnls * sp[0]->s_n * sizeof(t_sample);
BTW, "bufbytes" is a bit redundant, as you can just calculate it from "x->blksize".
---
dsp_add(var_io_tilde_perform, 2, x, sp[0]->s_n);
ALWAYS cast integers to "t_int" before passing them to "dsp_add"; otherwise it might crash on certain platforms. Here's the correct version:
dsp_add(var_io_tilde_perform, 2, x, (t_int)sp[0]->s_n);
Christof
On 19.09.2023 20:33, IOhannes m zmölnig wrote:
On 9/19/23 20:02, Alexandros Drymonitis wrote:
x->bufbytes = x->chnls*2*sp[0]->s_n;
what is this "2" supposed to represent?
mfdsar IOhannes
Pd-dev mailing list Pd-dev@lists.iem.at https://lists.puredata.info/listinfo/pd-dev
Both of you were right. The 2 wasn't necessary, and indeed, I forgot to multiply by the element type.
Thanks for the casting to t_int tip, wasn't aware of that.
On 9/19/23 23:17, Christof Ressi wrote:
what is this "2" supposed to represent?
This looks like a mistake to me. The buffer certainly does not have to be twice as large, as it is only used to copy the input.
To solve the mystery, you don't allocate the right amount of memory because you forgot about the element type:
x->bufbytes = x->chnls * sp[0]->s_n * sizeof(t_sample);
BTW, "bufbytes" is a bit redundant, as you can just calculate it from "x->blksize".
dsp_add(var_io_tilde_perform, 2, x, sp[0]->s_n);
ALWAYS cast integers to "t_int" before passing them to "dsp_add"; otherwise it might crash on certain platforms. Here's the correct version:
dsp_add(var_io_tilde_perform, 2, x, (t_int)sp[0]->s_n);
Christof
On 19.09.2023 20:33, IOhannes m zmölnig wrote:
On 9/19/23 20:02, Alexandros Drymonitis wrote:
x->bufbytes = x->chnls*2*sp[0]->s_n;
what is this "2" supposed to represent?
mfdsar 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
Am 20. September 2023 09:07:18 MESZ schrieb Alexandros Drymonitis adrcki@gmail.com:
Both of you were right. The 2 wasn't necessary, and indeed, I forgot to multiply by the element type.
Actually I assumed that "2" was meant to be the element size, and thus plain wrong (it would be "4" on single precision and "8" on double). So yes, use `sizeof(t_sample)`
mfg.sfg.jfd IOhannes