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); }