delay line with circular buffer code.

Jul 6, 2006 at 2:15pm

delay line with circular buffer code.

Hi everybody. I am trying to develop an interpolating delay object for MSP and Im having a few problems. At the moment Im just trying to develop a simple delay object using a circular buffer. I have a working inlet which i will use for the delay time, although currently Im using a fixed delay time of half the buffer length, just until i get the buffer working. The code compiles fine and you can load the object into a patch, it just crashes as soon as you turn on the audio. This could be because Im not freeing the allocated memory. I have a function to do this but Im not sure where to call it. Also, Im not sure if my perform routine is right. As always, any help would be greatly appreciated.
Thanks,
enda
————————–
#include “ext.h”
#include “z_dsp.h”
#include

#define BUFLENGTH 132300

// the subsample object. A signal delay object with subsample interpolation
// First test object will be a gain multiplier

void *subsample_class;

typedef struct _subsample
{
t_pxobject x_obj;
float x_deltime;
int x_bufcount;
float *buffer; //Is this the right place to create the buffer?
} t_subsample;

void *subsample_new(double deltime);
t_int *subsample_perform(t_int *w);
void subsample_dsp(t_subsample *x, t_signal **sp, short *count);
void subsample_float(t_subsample *x, t_float val); //inlet method

void main(void) //Initilisation routine.
{
setup((t_messlist **)&subsample_class,(method)subsample_new, (method)dsp_free,
(short)sizeof(t_subsample), 0L, 0);
addmess((method)subsample_dsp, “dsp”, A_CANT, 0); //maybe add other standard calc values here
addftx((method)subsample_float, 1);
dsp_initclass();

}

void *subsample_new(double val) // New instance routine
{
int i=0;
t_subsample *x = (t_subsample *)newobject(subsample_class);
dsp_setup((t_pxobject *)x,1);
floatin((t_object *)x,1); // one float inlet for delay time
outlet_new((t_pxobject *)x, “signal”);
x->x_deltime= 1.0;
x->x_bufcount=0;

return (x);
}

void subsample_float(t_subsample *x, float val) // right inlet method
{
// post(“Float in: %d”, val);
x->x_deltime = val;

}
//DSP method only need to pass signals here to our perform routine
//Also do any requireed calcs here.

void subsample_dsp(t_subsample* x, t_signal **sp, short* count)
{
dsp_add(subsample_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x);
x->buffer=(float*)malloc(sizeof(float)*BUFLENGTH); //allocate the buffer

//bzero(x->buffer, sizeof(float) *BUFLENGTH); could not find bzero, is this in another header file?
}

void subsample_free(t_subsample* x)
{
dsp_free((t_pxobject*) x);
free(x->buffer);
// bzero(x, sizeof(t_subsample)); where do we call this free routine?
}

// PERFORM ROUTINE
t_int *subsample_perform(t_int *w)
{
t_float *inL = (t_float *)(w[1]);
t_float *outL = (t_float *)(w[2]);

int n = (int)(w[3]); //this is our signal vector
t_subsample *x = (t_subsample *)w[4];

int nn = BUFLENGTH * 0.5; //Initially i will use a fixed delay of half the bufferlength
int count=0; //Once this is working i will use the inlet value to set the delay time.
float temp;

for (count=0; count
{
x->buffer[x->x_bufcount++] = *inL++; //store sample from 1st Signal Vector
if(x->x_bufcount = BUFLENGTH) //if end of buffer reached, go back to start.
x->x_bufcount = 0;

temp = x->x_bufcount+nn; // if our

if((temp) >= BUFLENGTH)
temp = (x->x_bufcount+nn) – BUFLENGTH;

*outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];

*outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];

}
return (w + 5); // always add one more than the 2nd argument in dsp_add()
}

#26701
Jul 6, 2006 at 2:25pm

I’d recommend allocing memory in your subsample_new routine, rather
than after calling the dsp_add function. Also, instead of bzero(),
you might find memset() of use.

Good luck,
Eric

On Jul 6, 2006, at 3:15 PM, Enda wrote:

> void subsample_dsp(t_subsample* x, t_signal **sp, short* count)
> {
> dsp_add(subsample_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]-
> >s_n, x);
> x->buffer=(float*)malloc(sizeof(float)*BUFLENGTH); //allocate
> the buffer
>
> //bzero(x->buffer, sizeof(float) *BUFLENGTH); could not find
> bzero, is this in another header file?
> }

#80121
Jul 6, 2006 at 2:44pm

Thanks Eric, i will try that. Any idea as to where/how exactly the subsample_free routine is called?
Thanks again,
enda

#80122
Jul 6, 2006 at 2:51pm

On Jul 6, 2006, at 3:44 PM, Enda wrote:

>
> Thanks Eric, i will try that. Any idea as to where/how exactly the
> subsample_free routine is called?

In your code as it stands, subsample_free will never get called. You
have to introduce your function at instantiation. Then it will get
called when your object is destroyed.

Here is where you should introduce your custom free method:

void main(void) //Initilisation routine.
{
setup((t_messlist **)&subsample_class,(method)subsample_new,
(method) subsample_free,
(short)sizeof(t_subsample), 0L, 0);
addmess((method)subsample_dsp, “dsp”, A_CANT, 0); //maybe add other
standard calc values here
addftx((method)subsample_float, 1);
dsp_initclass();

}

I think this is covered in the SDK though you may have to hunt a bit
for the information you need.

> Thanks again,

You are most welcome.

Eric

#80123
Jul 6, 2006 at 3:02pm

Ok, so I think the free routine is working now (thanks Eric), but still it crashes as soon as audio is switched on.
——————-
#include “ext.h”
#include “z_dsp.h”
#include

#include
#define BUFLENGTH 132300

// the subsample object. A signal delay object with subsample interpolation
// First test object will be a gain multiplier

void *subsample_class;

typedef struct _subsample
{
t_pxobject x_obj;
float x_deltime;
int x_bufcount;
float *buffer; //Is this the right place to create the buffer?
} t_subsample;

void *subsample_new(double deltime);
t_int *subsample_perform(t_int *w);
void subsample_dsp(t_subsample *x, t_signal **sp, short *count);
void subsample_float(t_subsample *x, t_float val); //inlet method
void subsample_free(t_subsample *x);

void main(void) //Initilisation routine.
{
setup((t_messlist **)&subsample_class,(method)subsample_new, (method) subsample_free,
(short)sizeof(t_subsample), 0L, 0);
addmess((method)subsample_dsp, “dsp”, A_CANT, 0); //maybe add other standard calc values here
addftx((method)subsample_float, 1);
dsp_initclass();

}

void subsample_free(t_subsample *x)
{
dsp_free((t_pxobject*) x);
free(x->buffer);
memset (x->buffer,’0′,BUFLENGTH);
// bzero(x, sizeof(t_subsample)); where do we call this free routine?
}

void *subsample_new(double val) // New instance routine
{
int i=0;
t_subsample *x = (t_subsample *)newobject(subsample_class);
dsp_setup((t_pxobject *)x,1);
floatin((t_object *)x,1); // one float inlet for delay time
outlet_new((t_pxobject *)x, “signal”);
x->x_deltime= 1.0;
x->x_bufcount=0;

return (x);
}

void subsample_float(t_subsample *x, float val) // right inlet method
{
// post(“Float in: %d”, val);
x->x_deltime = val;

}
//DSP method only need to pass signals here to our perform routine
//Also do any requireed calcs here.

void subsample_dsp(t_subsample* x, t_signal **sp, short* count)
{
dsp_add(subsample_perform, 4, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n, x);
x->buffer=(float*)malloc(sizeof(float)*BUFLENGTH); //allocate the buffer
memset (x->buffer,’0′,BUFLENGTH);
//bzero(x->buffer, sizeof(float) *BUFLENGTH); could not find bzero, is this in another header file?
}

// PERFORM ROUTINE
t_int *subsample_perform(t_int *w)
{
t_float *inL = (t_float *)(w[1]);
t_float *outL = (t_float *)(w[2]);

int n = (int)(w[3]); //this is our signal vector
t_subsample *x = (t_subsample *)w[4];

int nn = BUFLENGTH * 0.5; //Initially i will use a fixed delay of half the bufferlength
int count=0; //Once this is working i will use the inlet value to set the delay time.
float temp;

for (count=0; count
{
x->buffer[x->x_bufcount++] = *inL++; //store sample from 1st Signal Vector
if(x->x_bufcount = BUFLENGTH) //if end of buffer reached, go back to start.
x->x_bufcount = 0;

temp = x->x_bufcount+nn; // if our

if((temp) >= BUFLENGTH)
temp = (x->x_bufcount+nn) – BUFLENGTH;

*outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];

*outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];

}
return (w + 5); // always add one more than the 2nd argument in dsp_add()
}

#80124
Jul 6, 2006 at 4:24pm

Ok, the problem is definitly in the perform routine as a straight
*outL++ = *inL;
works fine.

My current perform routine is below but im not sure how the pointer to the buffer is working and how exactly it is incremented. Im aware that you should never access structure components inside the perform loop and that you should always put addresses into registers before entering the loop. Ive attmepted this but im a bit lost. If someone had a perform routine for a basis circular buffer I’d sure appreciate it.
Thanks again,
enda

// PERFORM ROUTINE
t_int *subsample_perform(t_int *w)
{
t_float *inL = (t_float *)(w[1]);
t_float *outL = (t_float *)(w[2]);
int n = (int)(w[3]); //this is our signal vector
t_subsample *x = (t_subsample *)w[4];

int nn = BUFLENGTH * 0.5; //fixed delay time for now
int count=0, bufcount=0;
int temp;
float* bufptr = x->buffer;
memset (x->buffer,’0′,BUFLENGTH);

for (count=0; count
{
bufptr++ = *inL++;
if(bufcount = BUFLENGTH) //if end of buffer reached,,,
bufcount = 0;
temp = bufcount+nn;
if((temp) >= BUFLENGTH)
temp = (bufcount+nn) – BUFLENGTH;

*outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];

}
return (w + 5); // always add one more than the 2nd argument in dsp_add()
}

#80125
Jul 6, 2006 at 5:01pm

>

Make sure you constrain x->x_bufcount + nn to the length of x->buffer
or you could get into trouble.

Perhaps you want to print some values out (like the values of all of
the pointers you’re dereferencing and the offsets).

> *outL++ = *inL++ + x->buffer[(x->x_bufcount + nn)];
>

_Mark

#80126
Jul 6, 2006 at 5:23pm

I would encourage you to look closely at the following lines of code:

> bufptr++ = *inL++;

and

> if(bufcount = BUFLENGTH) //if end of buffer reached,,,

Eric

#80127

You must be logged in to reply to this topic.