source for softclip~. this shows how to pass the object structure “x” into the audio perform function.
#include "m_pd.h" #include #include #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif /* ------------------------ softclip~ ----------------------------- */ /* tilde object to do a simple soft clipping algorithm. */ static t_class *softclip_class; typedef struct _softclip { t_object x_obj; /* obligatory header */ t_float gain; /* floats on the first inlet set the gain */ t_float sample_rate; t_float freq; } t_softclip; /* this is the actual performance routine which acts on the samples. It's called with a single pointer "w" which is our location in the DSP call list. We return a new "w" which will point to the next item after us. Meanwhile, w[0] is just a pointer to dsp-perform itself (no use to us), w[1] and w[2] are the input and output vector locations, and w[3] is the number of points to calculate. */ static t_int *softclip_perform(t_int *w) { t_softclip *x = (t_softclip *)(w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); int n = (int)(w[4]); // i like counting from zero, so i use samplenumber to count the offset from // the start of the in and out blocks int samplenumber = 0; float a = -0.5f; float b = 0.0; float c = 1.5f; float d = 0.0; float ingain; while (n--) { ingain = x->gain * *(in+samplenumber); if(ingain > 1) *(out+samplenumber) = 1.0f; else if(ingain < -1) *(out+samplenumber) = -1.0f; else *(out+samplenumber) = a * ingain * ingain * ingain + b * ingain * ingain + c * ingain + d; samplenumber++; } return (w+5); } /* called to start DSP. Here we call Pd back to add our perform routine to a linear callback list which Pd in turn calls to grind out the samples. */ static void softclip_dsp(t_softclip *x, t_signal **sp) { x->sample_rate = sp[0]->s_sr; dsp_add(softclip_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } static void *softclip_new(void) { t_softclip *x = (t_softclip *)pd_new(softclip_class); x->freq = 432.0f; outlet_new(&x->x_obj, gensym("signal")); return (x); } /* this routine, which must have exactly this name (with the "~" replaced by "_tilde) is called when the code is first loaded, and tells Pd how to build the "class". */ void softclip_tilde_setup(void) { softclip_class = class_new(gensym("softclip~"), (t_newmethod)softclip_new, 0, sizeof(t_softclip), 0, A_DEFFLOAT, 0); /* this is magic to declare that the leftmost, "main" inlet takes signals; other signal inlets are done differently... */ /* also installs gain as the leftmost inlet float */ CLASS_MAINSIGNALIN(softclip_class, t_softclip, gain); /* here we tell Pd about the "dsp" method, which is called back when DSP is turned on. */ class_addmethod(softclip_class, (t_method)softclip_dsp, gensym("dsp"), (t_atomtype)0); }
source for rms~. this shows how to allocate and deallocate an array
#include "m_pd.h" #include#include #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif /* ------------------------ rms~ ----------------------------- */ /* tilde object to take the absolute value of a signal at audio rate */ /* an argument for window size may be entered upon instantiation */ static t_class *rms_class; typedef struct _rms { t_object x_obj; // obligatory variable t_float x_f; // stores message recieved on audio inlet t_int window; // window size set by object argument t_float sum; // running sum of squared values t_float *squaretab; // table to hold squared values t_int tabread1; // pointer offset for newest table value t_int tabread2; // pointer offset for oldest table value } t_rms; static t_int *rms_perform(t_int *w) { t_rms *x = (t_rms *)(w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); int n = (int)(w[4]); // number of samples passed int blocksize = n; // sample from 0 up int sample = 0; // mean of squared value float mean = 0; // used to multiply instead of divide float oneOverWindow = 1.0f/x->window; while (n--) { // store newest squared value in the table *(x->squaretab+x->tabread1) = *(in+sample) * *(in+sample); // add this value to the running sum x->sum += *(x->squaretab+x->tabread1); // subtract the oldest value in the table x->sum -= *(x->squaretab+x->tabread2); // compute the current mean value mean = x->sum * oneOverWindow; // take the square root and send the value to outlet *(out+sample) = sqrt(mean); // increment to next sample sample++; // increment to next table position x->tabread1++; x->tabread2++; // reset to beginning of table if(x->tabread1 >= x->window) x->tabread1 = 0; // increment to next table position // reset to beginning of table if(x->tabread2 >= x->window) x->tabread2 = 0; } return (w+5); } static void rms_dsp(t_rms *x, t_signal **sp) { dsp_add(rms_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } // setting window size void rms_windowset(t_rms *x, t_floatarg f) { // using a good value if( f >= 256 && f <= 4096 ) x->window = f; // blocking bad values else if( f < 256 ) { x->window = 256; post("rms~: window size must be set to a value between 256 and 4096"); } else if( f > 4096 ) { x->window = 4096; post("rms~: window size must be set to a value between 256 and 4096"); } } static void *rms_new(t_floatarg f) { int i; t_rms *x = (t_rms *)pd_new(rms_class); outlet_new(&x->x_obj, gensym("signal")); x->squaretab = 0; x->x_f = 0; // initialize the sum x->sum = 0; // changing windowsize on creation rms_windowset(x, f); // intializing table for largest window size x->squaretab = (t_float *)malloc(4097 * sizeof(t_float)); // initialzing the table to 0 for( i = 0; i < x->window; i++) *(x->squaretab+i) = 0; // initializing newest sample x->tabread1 = 0; // initializing oldest sample x->tabread2 = 1; return (x); } // function to clear the allocated square table static void rms_free(t_rms *x) { free(x->squaretab); if(x->squaretab != 0) { free(x->squaretab); x->squaretab = 0; } } void rms_tilde_setup(void) { rms_class = class_new(gensym("rms~"), (t_newmethod)rms_new, (t_method)rms_free, sizeof(t_rms), 0, A_DEFFLOAT, 0); CLASS_MAINSIGNALIN(rms_class, t_rms, x_f); class_addmethod(rms_class, (t_method)rms_dsp, gensym("dsp"), (t_atomtype)0); }