// // Copyright: Copyright 2003 Craig Stuart Sapp // Programmer: Craig Stuart Sapp // Creation Date: Tue Mar 11 15:45:02 PST 2003 // Last Modified: Tue Mar 11 15:59:28 PST 2003 // Filename: mybiquad.c // Web Address: http://peabody.sapp.org/class/dmp2/lab/mybiquad/mybiquad.c // Syntax: C; Max4/MSP2 External Object; CodeWarrior 6.0 // OS: Mac OS 9; PPC // // Description: A generic biquad filter used for resonating a sound. // #include "ext.h" #include "z_dsp.h" typedef struct { t_pxobject msp_data; // must always be the first field; used by MSP float lastinput; // last signal value to come into filter. float lastinput2; // second to last signal value to come into filter. float lastoutput; // last signal value to go out of filter. float lastoutput2;// second to last signal value to go out of filter. float a0; // zeroth-order feedforward gain float a1; // first-order feedforward gain float a2; // second-order feedforward gain float b1; // first-order feedback gain float b2; // second-order feedback gain } MyObject; void* object_data; // pointer to data for object (created in setup()); // function declarations: void main (void); void* create_object (void); void MessageDSP (MyObject* mo, t_signal** signal, short* count); void MessageClear (MyObject* mo); void InputA0 (MyObject* mo, float value); void InputA1 (MyObject* mo, float value); void InputA2 (MyObject* mo, float value); void InputB1 (MyObject* mo, float value); void InputB2 (MyObject* mo, float value); t_int* Perform (t_int *parameters); ////////////////////////////////////////////////////////////////////////// // // Initialization functions: // void main(void) { setup((t_messlist**)&object_data, (method)create_object, (method)dsp_free, (short)sizeof(MyObject), NULL, A_NOTHING); addftx((method)InputB2, 1); addftx((method)InputB1, 2); addftx((method)InputA2, 3); addftx((method)InputA1, 4); addftx((method)InputA0, 5); addmess((method)MessageDSP, "dsp", A_CANT, A_NOTHING); addmess((method)MessageClear, "clear", A_NOTHING); dsp_initclass(); } ////////////////////////////// // // create_object -- object initializing function. This function is // called by the setup() function inside of main(). Place code // here which will be used to initialized your data structure, // as well as the actual creation of the data storage itself. // The setup function will cause the pointer object_data to point // to the created data storage. // void* create_object(void) { MyObject *mo = (MyObject*)newobject(object_data); dsp_setup((t_pxobject*)mo, 1); // 1 signal input outlet_new((t_pxobject*)mo, "signal"); // outlet 1 floatin(mo, 1); floatin(mo, 2); floatin(mo, 3); floatin(mo, 4); floatin(mo, 5); // set all of the gain coefficients to zero like the biquad~ mo->a0 = 0.0; mo->a1 = 0.0; mo->a2 = 0.0; mo->b1 = 0.0; mo->b2 = 0.0; MessageClear(mo); return mo; } ////////////////////////////////////////////////////////////////////////// // // Behavior functions: // ////////////////////////////// // // Input[AB][012] -- set the gains for the filter. // void InputA0 (MyObject* mo, float value) { mo->a0 = value; } void InputA1 (MyObject* mo, float value) { mo->a1 = value; } void InputA2 (MyObject* mo, float value) { mo->a2 = value; } void InputB1 (MyObject* mo, float value) { mo->b1 = value; } void InputB2 (MyObject* mo, float value) { mo->b2 = value; } ////////////////////////////// // // MessageDSP -- What to do when a "dsp" message arrives into the object. // void MessageDSP(MyObject* mo, t_signal** signal, short* count) { #pragma unused(count) dsp_add(Perform, 5, 5, mo, signal[0]->s_vec, signal[1]->s_vec, signal[0]->s_n); } ////////////////////////////// // // MessageClear -- clear the memory of the past signal value (set it to 0). // void MessageClear(MyObject *mo) { mo->lastinput = 0.0; mo->lastinput2 = 0.0; mo->lastoutput = 0.0; mo->lastoutput2 = 0.0; } ////////////////////////////// // // Perform -- do the calculations for one sample group. // the for-loop implements the difference equation for a biquad filter: // y[n] = a0*x[n] + a1*x[n-1] + a2*x[n-2] - b1*y[n-1] - b2*y[n-2] // t_int* Perform(t_int *parameters) { long pcount = (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; ia0 * input[i] + mo->a1 * mo->lastinput + mo->a2 * mo->lastinput2 - mo->b1 * mo->lastoutput - mo->b2 * mo->lastoutput2; mo->lastinput2 = mo->lastinput; mo->lastoutput2 = mo->lastoutput; mo->lastinput = input[i]; mo->lastoutput = output[i]; } return parameters+pcount+1; }