[Csnd] plugin opcode devlopment - problems with pointer allocation

Hello everybody!

I have trouble with my first opcode implementation.
There is something going wrong in the init function and i don’t get it to work in csound. it’s compiling and i am able to call the opcode but i get a seg fault.
im working with the csound 6 sdk.

I implemented a error message to see where the problem is resulting from. and it seems that i do something wrong in my thomas_init function.
the init function is starting, but there is a problem with my pointers.
but i really don’t have a clue what i do wrong. i consulted a lot of examples and all tutorials i found.

maybe someone has the time to help me to debug this

- Philipp

#include <math.h>
#include <stdint.h>
#include "csdl.h"
#include "csoundCore.h"

#include "xine.h"

#define THOMAS_MAXCHN 36  

typedef struct {
  OPDS h;
  MYFLT *aout_x[THOMAS_MAXCHN], *aout_y[THOMAS_MAXCHN],
    *aout_z[THOMAS_MAXCHN]; /* output */
  MYFLT *b, *delta_time, *skip, *in_x, *in_y, *in_z, *n_particles, *max_deviation; /* input */
  MYFLT n_voices; /* internal variables */
  MYFLT skip_count;
  MYFLT x_start;
  MYFLT y_start;
  MYFLT z_start;
  MYFLT max_dev; 
} THOMAS;

int32_t thomas_init(CSOUND *csound, THOMAS *p){
  printf("Init Start\n");
  if (p->in_x == NULL || p->in_y == NULL || p->in_z == NULL || 
    p->n_particles == NULL || p->max_deviation == NULL) {
    csound->Message(csound, "Error: One or more pointers are NULL\n");
    return NOTOK;
  }
  p->skip_count = *p->skip;
  p->x_start = *p->in_x;
  p->y_start = *p->in_y;
  p->z_start = *p->in_z;
  p->n_voices = *p->n_particles;
  p->max_dev = *p->max_deviation;
  return OK;
}

int32_t thomas_process(CSOUND *csound, THOMAS *p){
  printf("Proc Start\n");
  /* sample accurate mechanism */
  uint32_t offset = p->h.insdshead->ksmps_offset;
  uint32_t early  = p->h.insdshead->ksmps_no_end;

  /* variables */
  uint32_t sample_count = CS_KSMPS;
  uint32_t sample_index, channel_index;
  int32_t voices = p->n_voices;
  int32_t voice;
  MYFLT max_deviation = p->max_dev;
  MYFLT deviation;
  MYFLT x, y, z, xx, yy;
  MYFLT b = *p->b;
  MYFLT time = *p->delta_time;
  int32_t skip = (int32_t)p->skip_count;
  MYFLT *out_x, *out_y, *out_z;
  
  /* Process channels: */
  if (UNLIKELY(early))
    sample_count -= early;
  for (channel_index = 0; channel_index < voices; channel_index++){
    out_x = p->aout_x[channel_index];
    out_y = p->aout_y[channel_index];
    out_z = p->aout_z[channel_index];
    deviation = signed_deviation(max_deviation, voices, channel_index);
    if (UNLIKELY(offset)){
      memset(out_x, '\0', offset*sizeof(MYFLT));
      memset(out_y, '\0', offset*sizeof(MYFLT));
      memset(out_z, '\0', offset*sizeof(MYFLT));
    } 
    if (UNLIKELY(early)){
      memset(&out_x[sample_count], '\0', early*sizeof(MYFLT));
      memset(&out_y[sample_count], '\0', early*sizeof(MYFLT));
      memset(&out_z[sample_count], '\0', early*sizeof(MYFLT));
    }
    for (sample_index = offset;
	 sample_index < sample_count;
	 sample_index++){
      do {
	/* fuctions for the thomas attractor
	   https://en.wikipedia.org/wiki/Thomas'_cyclically_symmetric_attractor
	 */
	xx = ((-b * (x + deviation)) + sin((y + deviation))) * time;
	yy = ((-b * (y + deviation)) + sin((z + deviation))) * time;
	z = ((-b * (z + deviation)) + sin((x + deviation))) * time;
	x = xx;
	y = yy;
      } while (--skip > 0);
      out_x[sample_index] = x;
      out_y[sample_index] = y;
      out_z[sample_index] = z;
    }            
  }
  
  return OK;
}

#define S(x)    sizeof(x)
static OENTRY localops[] = {
  {"thomas", S(THOMAS), 0, 7, "a[]a[]a[]", "kkiiiiii",
   (SUBR) thomas_init, (SUBR) thomas_process}
};

LINKAGE

Csound mailing list
Csound@listserv.heanet.ie
https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND
Send bugs reports to
        Issues · csound/csound · GitHub
Discussions of bugs and features can be posted here

For array variables you need to use ARRAYDAT* and manage the arrays yourself.
They are not simple MYFLT* arrays, but a data structure.

In the Csound sources, there are examples of how this is done, Opcodes/arrays.c

Prof. Victor Lazzarini
Maynooth University
Ireland

Thanks for the advice!

It’s really a lot to dig in with using output arrays.
But when i’m right i can just use ’tabinit’ to allocate memory and create a variable für this?

Also, i guess, there changed a bit since csound 6.
e.g. ‚createVariable‘ has changed. is this for the new typ of variable initialisation and usage?
is this backwards compatible to csound 6?

You should not need to call createVariable directly at all. Look at the inline functions in include/arrays.h, it contains
have everything one would need to use arrays (tabinit, tabinit_like, tabcheck). However, using arrays is more involved
than dealing with i,a,k vars.

The ABI or API is not backward compatible. The Csound language is (or should be, bar maybe some
issues we don’t know that need to be fixed). Also note that 6.x is EOL and we are not going to be
developing it anymore. It’s up to third-party developers what they want to do, but we would advise
to develop for Csound 7.