/**
simple low-pass filter that averages successive samples by:
saving the value of the last sample in a vector
averaging it with the first sample of the next vector
*/
/**
include files
*/
#include "ext.h" // should always be first
#include "ext_obex.h" // followed by ext_obex.h
#include "z_dsp.h" // ONLY MSP
/**
structure declaration
*/
typedef struct _myfilter
{
t_pxobject f_obj; // t_pbxobject in MSP, for Max use t_object
t_float f_sample; // internal state
} t_myfilter;
/**
initialization routine
*/
void *myfilter_class;
void *myfilter_new(double val);
t_int *myfilter_perform(t_int *w);
void myfilter_dsp(t_myfilter *x, t_signal **sp, short *count);
int main(void)
{
t_class *c; // always first
c = class_new("myfilter", (method)myfilter_new, (method)dsp_free, sizeof(t_myfilter), NULL, 0);
// creating the class with the new instance routine and the free function dsp_free
class_addmethod(c, (method)myfilter_dsp, "dsp", A_CANT, 0);// respond to the dsp message
// (sent to MSP objects when audio is turned on/off)
// binds C method myfilter_dsp to the text symbol "dsp"
class_dspinit(c); // ONLY DSP
// adds some standard method handlers for internal messages used by all signal objects
class_register(CLASS_BOX, c);
// will be searched when typing it into a Max object box
myfilter_class = c;
// assign the class we’ve created to a global variable so we can use it when creating new instances
return 0;
}
/**
new instance routine
*/
void *myfilter_new(double val)
{
t_myfilter *x = object_alloc(myfilter_class);
dsp_setup((t_pxobject *)x, 1); // creating one signal inlet
outlet_new((t_object *)x, "signal"); // creating one signal outlet
return (x);
}
/**
dsp method
*/
void myfilter_dsp(t_myfilter *x, t_signal **sp, short *count)
{
dsp_add(myfilter_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
x->f_sample = 0; // initialize internal state
}
/**
perform routine
*/
t_int *myfilter_perform(t_int *w)
{
t_myfilter *x = (t_myfilter *)w[1];
t_float *in = (t_float *)w[2];
t_float *out = (t_float *)w[3];
int n = (int)w[4];
t_float samp = x->f_sample; // samp float reads from internal state
t_float val;
while (n--) { // loop that performs the average continously
val = *in++; // reads new sample
*out++ = (val + samp) * 0.5; // average
samp = val;
}
x->f_sample = samp; // save to internal state
return w + 5;
}