// // Programmer: Craig Stuart Sapp // Creation Date: Mon Mar 31 08:49:01 PST 2003 // Last Modified: Mon Mar 31 09:17:04 PST 2003 // Filename: mydelayline.c // Web Address: http://peabody.sapp.org/class/dmp2/lab/mydelayline/mydelayline.c // Syntax: C; Max4/MSP2 External Object; CodeWarrior 6.0 // OS: Mac OS 9; PPC // // Description: Demonstration of how to create audio delay lines. // #include "ext.h" #include "z_dsp.h" typedef struct { t_pxobject msp_data; // must always be the first field; used by MSP float* data; // data storage for delayline long index; // where to read the data long allocsize; // allocation size in memory long size; // delay line size (<= allocsize) } MyObject; void* object_data; // pointer to data for object (created in setup()); // function declarations: void main (void); void* create_object (long maxsize); void destroy_object (MyObject* mo); void InputSize (MyObject* mo, long newsize); void MessageDSP (MyObject* mo, t_signal** signal, short* count); void MessageClear (MyObject* mo); t_int* Perform (t_int *parameters); float incrementDelayline (MyObject* mo, float value); ////////////////////////////////////////////////////////////////////////// // // Initialization functions: // ////////////////////////////// // // main -- called once when object is created in a Max/MSP patch window. // void main(void) { setup((t_messlist**)&object_data, (method)create_object, (method)destroy_object, (short)sizeof(MyObject), NULL, A_LONG, A_NOTHING); addinx((method)InputSize, 1); // input 2: size of delay addmess((method)MessageDSP, "dsp", A_CANT, A_NOTHING); addmess((method)MessageClear, "clear", A_NOTHING); dsp_initclass(); } ////////////////////////////// // // create_object -- object initializing function. // void* create_object(long maxsize) { MyObject *mo = (MyObject*)newobject(object_data); // create data storage dsp_setup((t_pxobject*)mo, 1); // input 2 outlet_new((t_pxobject*)mo, "signal"); // output 1 intin(mo, 1); // input 2: size of delay if (maxsize < 1) { post("Error: buffer size too small, setting it to 1000 samples."); maxsize = 1000; } mo->data = (float*)malloc(maxsize * sizeof(float)); mo->allocsize = maxsize; mo->size = maxsize; MessageClear(mo); return mo; // return pointer to data storage } ////////////////////////////// // // destroy_object -- what to do when removing an object from a patch window. // void destroy_object(MyObject* mo) { dsp_free(&(mo->msp_data)); free(mo->data); mo->data = NULL; mo->allocsize = 0; mo->size = 0; mo->index = 0; } ////////////////////////////////////////////////////////////////////////// // // Behavior functions: // ////////////////////////////// // // InputSize -- input a new delayline size (must be equal or smaller // than the initial size of the delayline. // void InputSize(MyObject* mo, long value) { if (value < 0) { post("Size too small, setting size to default value."); value = mo->allocsize; } else if (value > mo->allocsize) { post("Size too large, setting size to default value."); value = mo->allocsize; } mo->size = value; MessageClear(mo); } ////////////////////////////// // // MessageDSP -- What to do when a "dsp" message arrives into the object. // void MessageDSP(MyObject* mo, t_signal** signal, short* count) { #pragma unused(count) int paramcount = 5; dsp_add(Perform, paramcount, paramcount, mo, signal[0]->s_vec, signal[1]->s_vec, signal[0]->s_n); } ////////////////////////////// // // MessageClear -- empty the contents of the delayline. // void MessageClear(MyObject* mo) { int i; for (i=0; iallocsize; i++) { mo->data[i] = 0.0; } mo->index = 0; } ////////////////////////////// // // Perform -- do the action for one sample group (number of samples // specified by the value w[3], which is to copy the input data into // the output data. // t_int* Perform(t_int *parameters) { long paramcount = (long) (parameters[1]); MyObject *mo = (MyObject*)(parameters[2]); t_float *input = (t_float*) (parameters[3]); t_float *output = (t_float*) (parameters[4]); long count = (long) (parameters[5]); long i; for (i=0; isize == 0) { return value; } output = mo->data[mo->index]; mo->data[mo->index] = value; mo->index++; if (mo->index >= mo->size) { mo->index = 0; } return output; }