/* For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. iemlib1 written by Thomas Musil, Copyright (c) IEM KUG Graz Austria 2000 - 2011 */ #include "m_pd.h" #include "iemlib.h" #include /* ---------- filter~ - slow dynamic filter-kernel 1. and 2. order ----------- */ /* -------------- now with single and double precision option ---------------- */ /* ------- sp ..... single precision, ---- dp ..... double precision --------- */ typedef struct _filter_tilde_sp_para t_filter_tilde_sp_para; typedef void (*filt_calc_sp_fun_ptr)(t_filter_tilde_sp_para *); struct _filter_tilde_sp_para { t_float wn1;// old wn of biquad recursion t_float wn2;// two times old wn of biquad recursion t_float a0;// wn factor of numerator term of biquad recursion t_float a1;// wn1 factor of numerator term of biquad recursion t_float a2;// wn2 factor of numerator term of biquad recursion t_float b1;// wn1 factor of denominator term of biquad recursion t_float b2;// wn2 factor of denominator term of biquad recursion t_float pi_over_sr;// pi/samplerate t_float cur_f;// current frequency t_float cur_l;// current bilinear transformed frequency t_float cur_a;// current damping t_float cur_b;// current freqency shifting factor t_float delta_f;// frequency ratio from previous to current frequency t_float delta_a;// damping ratio from previous to current damping t_float delta_b;// freqency shift ratio from previous to current freqency shift t_float end_f;// destination frequency t_float end_a;// destination damping t_float end_b;// destination freqency shift t_float ticks_per_interpol_time;// dsp ticks per interpolation time intervall t_float rcp_ticks;// reciprocal number of dsp ticks within intervall t_float interpol_time;// interpolation time int ticks;// number of dsp ticks within intervall int counter_f;// number of dsp ticks to compute new frequency int counter_a;// number of dsp ticks to compute new damping int counter_b;// number of dsp ticks to compute new frequency shift int inlet3_is_Q;// if flag is HIGH, the third inlet (Q) has to be inverted to damping int filter_function_is_highpass;// flag is HIGH if filter has highpass characteristic int filter_function_is_first_order;// flag is HIGH if filter is first order int event_mask;// a three bit mask: Bit 0 is HIGH during frequency ramp, Bit 1 is HIGH during damping ramp, Bit 2 is HIGH during frequency shift ramp filt_calc_sp_fun_ptr calc; }; typedef struct _filter_tilde_dp_para t_filter_tilde_dp_para; typedef void (*filt_calc_dp_fun_ptr)(t_filter_tilde_dp_para*); struct _filter_tilde_dp_para { double wn1;// old wn of biquad recursion double wn2;// two times old wn of biquad recursion double a0;// wn factor of numerator term of biquad recursion double a1;// wn1 factor of numerator term of biquad recursion double a2;// wn2 factor of numerator term of biquad recursion double b1;// wn1 factor of denominator term of biquad recursion double b2;// wn2 factor of denominator term of biquad recursion double pi_over_sr;// pi/samplerate double cur_f;// current frequency double cur_l;// current bilinear transformed frequency double cur_a;// current damping double cur_b;// current freqency shifting factor double delta_f;// frequency ratio from previous to current frequency double delta_a;// damping ratio from previous to current damping double delta_b;// freqency shift ratio from previous to current freqency shift double end_f;// destination frequency double end_a;// destination damping double end_b;// destination freqency shift double ticks_per_interpol_time;// dsp ticks per interpolation time intervall double rcp_ticks;// reciprocal number of dsp ticks within intervall double interpol_time;// interpolation time int ticks;// number of dsp ticks within intervall int counter_f;// number of dsp ticks to compute new frequency int counter_a;// number of dsp ticks to compute new damping int counter_b;// number of dsp ticks to compute new frequency shift int inlet3_is_Q;// if flag is HIGH, the third inlet (Q) has to be inverted to damping int filter_function_is_highpass;// flag is HIGH if filter has highpass characteristic int filter_function_is_first_order;// flag is HIGH if filter is first order int event_mask;// a three bit mask: Bit 0 is HIGH during frequency ramp, Bit 1 is HIGH during damping ramp, Bit 2 is HIGH during frequency shift ramp filt_calc_dp_fun_ptr calc; }; typedef union _filt_para { t_filter_tilde_sp_para sp; t_filter_tilde_dp_para dp; } t_filt_para; typedef struct _filter_tilde { t_object x_obj; t_filt_para x_para; int x_precision_dp1_sp0; t_outlet *x_debug_outlet; t_atom x_at[5]; t_float x_float_sig_in; } t_filter_tilde; static t_class *filter_tilde_class; static void filter_tilde_sp_dummy(t_filter_tilde_sp_para *x) { } static void filter_tilde_dp_dummy(t_filter_tilde_dp_para *x) { } static void filter_tilde_sp_lp1(t_filter_tilde_sp_para *x) { t_float al; al = x->cur_a * x->cur_l; x->a0 = 1.0f/(1.0f + al); x->a1 = x->a0; x->b1 = (al - 1.0f)*x->a0; } static void filter_tilde_sp_lp2(t_filter_tilde_sp_para *x) { t_float l, al, bl2, rcp; l = x->cur_l; al = l*x->cur_a; bl2 = l*l*x->cur_b + 1.0f; rcp = 1.0f/(al + bl2); x->a0 = rcp; x->a1 = 2.0f*rcp; x->a2 = x->a0; x->b1 = rcp*2.0f*(bl2 - 2.0f); x->b2 = rcp*(al - bl2); } static void filter_tilde_sp_hp1(t_filter_tilde_sp_para *x) { t_float al, rcp; al = x->cur_a * x->cur_l; rcp = 1.0f/(1.0f + al); x->a0 = rcp*al; x->a1 = -x->a0; x->b1 = rcp*(al - 1.0f); } static void filter_tilde_sp_hp2(t_filter_tilde_sp_para *x) { t_float l, al, bl2, rcp; l = x->cur_l; bl2 = l*l*x->cur_b + 1.0f; al = l*x->cur_a; rcp = 1.0f/(al + bl2); x->a0 = rcp*(bl2 - 1.0f); x->a1 = -2.0f*x->a0; x->a2 = x->a0; x->b1 = rcp*2.0f*(bl2 - 2.0f); x->b2 = rcp*(al - bl2); } static void filter_tilde_sp_rp2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a; rcp = 1.0f/(al + l2); x->a0 = rcp*l; x->a2 = -x->a0; x->b1 = rcp*2.0f*(l2 - 2.0f); x->b2 = rcp*(al - l2); } static void filter_tilde_sp_bp2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a; rcp = 1.0f/(al + l2); x->a0 = rcp*al; x->a2 = -x->a0; x->b1 = rcp*2.0f*(l2 - 2.0f); x->b2 = rcp*(al - l2); } static void filter_tilde_sp_bs2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a; rcp = 1.0f/(al + l2); x->a0 = rcp*l2; x->a1 = rcp*2.0f*(2.0f - l2); x->a2 = x->a0; x->b1 = -x->a1; x->b2 = rcp*(al - l2); } static void filter_tilde_sp_rpw2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a/x->cur_f; rcp = 1.0f/(al + l2); x->a0 = rcp*l; x->a2 = -x->a0; x->b1 = rcp*2.0f*(l2 - 2.0f); x->b2 = rcp*(al - l2); } static void filter_tilde_sp_bpw2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a/x->cur_f; rcp = 1.0f/(al + l2); x->a0 = rcp*al; x->a2 = -x->a0; x->b1 = rcp*2.0f*(l2 - 2.0f); x->b2 = rcp*(al - l2); } static void filter_tilde_sp_bsw2(t_filter_tilde_sp_para *x) { t_float l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0f; al = l*x->cur_a/x->cur_f; rcp = 1.0f/(al + l2); x->a0 = rcp*l2; x->a1 = rcp*2.0f*(2.0f - l2); x->a2 = x->a0; x->b1 = -x->a1; x->b2 = rcp*(al - l2); } static void filter_tilde_sp_ap1(t_filter_tilde_sp_para *x) { t_float al; al = x->cur_a * x->cur_l; x->a0 = (1.0f - al)/(1.0f + al); x->b1 = -x->a0; } static void filter_tilde_sp_ap2(t_filter_tilde_sp_para *x) { t_float l, al, bl2, rcp; l = x->cur_l; bl2 = l*l*x->cur_b + 1.0f; al = l*x->cur_a; rcp = 1.0f/(al + bl2); x->a1 = rcp*2.0f*(2.0f - bl2); x->a0 = rcp*(bl2 - al); x->b1 = -x->a1; x->b2 = -x->a0; } static void filter_tilde_dp_lp1(t_filter_tilde_dp_para *x) { double al; al = x->cur_a * x->cur_l; x->a0 = 1.0/(1.0 + al); x->a1 = x->a0; x->b1 = (al - 1.0)*x->a0; } static void filter_tilde_dp_lp2(t_filter_tilde_dp_para *x) { double l, al, bl2, rcp; l = x->cur_l; al = l*x->cur_a; bl2 = l*l*x->cur_b + 1.0; rcp = 1.0/(al + bl2); x->a0 = rcp; x->a1 = 2.0*rcp; x->a2 = x->a0; x->b1 = rcp*2.0*(bl2 - 2.0); x->b2 = rcp*(al - bl2); } static void filter_tilde_dp_hp1(t_filter_tilde_dp_para *x) { double al, rcp; al = x->cur_a * x->cur_l; rcp = 1.0/(1.0 + al); x->a0 = rcp*al; x->a1 = -x->a0; x->b1 = rcp*(al - 1.0); } static void filter_tilde_dp_hp2(t_filter_tilde_dp_para *x) { double l, al, bl2, rcp; l = x->cur_l; bl2 = l*l*x->cur_b + 1.0; al = l*x->cur_a; rcp = 1.0/(al + bl2); x->a0 = rcp*(bl2 - 1.0); x->a1 = -2.0*x->a0; x->a2 = x->a0; x->b1 = rcp*2.0*(bl2 - 2.0); x->b2 = rcp*(al - bl2); } static void filter_tilde_dp_rp2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a; rcp = 1.0/(al + l2); x->a0 = rcp*l; x->a2 = -x->a0; x->b1 = rcp*2.0*(l2 - 2.0); x->b2 = rcp*(al - l2); } static void filter_tilde_dp_bp2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a; rcp = 1.0/(al + l2); x->a0 = rcp*al; x->a2 = -x->a0; x->b1 = rcp*2.0*(l2 - 2.0); x->b2 = rcp*(al - l2); } static void filter_tilde_dp_bs2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a; rcp = 1.0/(al + l2); x->a0 = rcp*l2; x->a1 = rcp*2.0*(2.0 - l2); x->a2 = x->a0; x->b1 = -x->a1; x->b2 = rcp*(al - l2); } static void filter_tilde_dp_rpw2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a/x->cur_f; rcp = 1.0/(al + l2); x->a0 = rcp*l; x->a2 = -x->a0; x->b1 = rcp*2.0*(l2 - 2.0); x->b2 = rcp*(al - l2); } static void filter_tilde_dp_bpw2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a/x->cur_f; rcp = 1.0/(al + l2); x->a0 = rcp*al; x->a2 = -x->a0; x->b1 = rcp*2.0*(l2 - 2.0); x->b2 = rcp*(al - l2); } static void filter_tilde_dp_bsw2(t_filter_tilde_dp_para *x) { double l, al, l2, rcp; l = x->cur_l; l2 = l*l + 1.0; al = l*x->cur_a/x->cur_f; rcp = 1.0/(al + l2); x->a0 = rcp*l2; x->a1 = rcp*2.0*(2.0 - l2); x->a2 = x->a0; x->b1 = -x->a1; x->b2 = rcp*(al - l2); } static void filter_tilde_dp_ap1(t_filter_tilde_dp_para *x) { double al; al = x->cur_a * x->cur_l; x->a0 = (1.0 - al)/(1.0 + al); x->b1 = -x->a0; } static void filter_tilde_dp_ap2(t_filter_tilde_dp_para *x) { double l, al, bl2, rcp; l = x->cur_l; bl2 = l*l*x->cur_b + 1.0; al = l*x->cur_a; rcp = 1.0/(al + bl2); x->a1 = rcp*2.0*(2.0 - bl2); x->a0 = rcp*(bl2 - al); x->b1 = -x->a1; x->b2 = -x->a0; } static void filter_tilde_dsp_sp_tick(t_filter_tilde_sp_para *x) { if(x->event_mask) { if(x->counter_f) { float l, si, co; if(x->counter_f <= 1) { x->cur_f = x->end_f; x->counter_f = 0; x->event_mask &= 6;/*set event_mask_bit 0 = 0*/ } else { x->counter_f--; x->cur_f *= x->delta_f; } l = x->cur_f * x->pi_over_sr; if(l < 1.0e-20f) x->cur_l = 1.0e20f; else if(l > 1.57079632f) x->cur_l = 0.0f; else { si = sin(l); co = cos(l); x->cur_l = co/si; } } if(x->counter_a) { if(x->counter_a <= 1) { x->cur_a = x->end_a; x->counter_a = 0; x->event_mask &= 5;/*set event_mask_bit 1 = 0*/ } else { x->counter_a--; x->cur_a *= x->delta_a; } } if(x->counter_b) { if(x->counter_b <= 1) { x->cur_b = x->end_b; x->counter_b = 0; x->event_mask &= 3;/*set event_mask_bit 2 = 0*/ } else { x->counter_b--; x->cur_b *= x->delta_b; } } (*(x->calc))(x); /* stability check */ if(x->filter_function_is_first_order) { if(x->b1 <= -0.9999998f) x->b1 = -0.9999998f; else if(x->b1 >= 0.9999998f) x->b1 = 0.9999998f; } else { float discriminant = x->b1 * x->b1 + 4.0f * x->b2; if(x->b1 <= -1.9999996f) x->b1 = -1.9999996f; else if(x->b1 >= 1.9999996f) x->b1 = 1.9999996f; if(x->b2 <= -0.9999998f) x->b2 = -0.9999998f; else if(x->b2 >= 0.9999998f) x->b2 = 0.9999998f; if(discriminant >= 0.0f) { if(0.9999998f - x->b1 - x->b2 < 0.0f) x->b2 = 0.9999998f - x->b1; if(0.9999998f + x->b1 - x->b2 < 0.0f) x->b2 = 0.9999998f + x->b1; } } //post("float a0=%f, a1=%f, a2=%f, b1=%f, b2=%f", x->a0, x->a1, x->a2, x->b1, x->b2); } } static void filter_tilde_dsp_dp_tick(t_filter_tilde_dp_para *x) { if(x->event_mask) { if(x->counter_f) { double l, si, co; if(x->counter_f <= 1) { x->cur_f = x->end_f; x->counter_f = 0; x->event_mask &= 6;/*set event_mask_bit 0 = 0*/ } else { x->counter_f--; x->cur_f *= x->delta_f; } l = x->cur_f * x->pi_over_sr; if(l < 1.0e-20) x->cur_l = 1.0e20; else if(l > 1.57079632) x->cur_l = 0.0; else { si = sin(l); co = cos(l); x->cur_l = co/si; } } if(x->counter_a) { if(x->counter_a <= 1) { x->cur_a = x->end_a; x->counter_a = 0; x->event_mask &= 5;/*set event_mask_bit 1 = 0*/ } else { x->counter_a--; x->cur_a *= x->delta_a; } } if(x->counter_b) { if(x->counter_b <= 1) { x->cur_b = x->end_b; x->counter_b = 0; x->event_mask &= 3;/*set event_mask_bit 2 = 0*/ } else { x->counter_b--; x->cur_b *= x->delta_b; } } (*(x->calc))(x); /* stability check */ if(x->filter_function_is_first_order) { if(x->b1 <= -0.9999998) x->b1 = -0.9999998; else if(x->b1 >= 0.9999998) x->b1 = 0.9999998; } else { double discriminant = x->b1 * x->b1 + 4.0 * x->b2; if(x->b1 <= -1.9999996) x->b1 = -1.9999996; else if(x->b1 >= 1.9999996) x->b1 = 1.9999996; if(x->b2 <= -0.9999998) x->b2 = -0.9999998; else if(x->b2 >= 0.9999998) x->b2 = 0.9999998; if(discriminant >= 0.0) { if(0.9999998 - x->b1 - x->b2 < 0.0) x->b2 = 0.9999998 - x->b1; if(0.9999998 + x->b1 - x->b2 < 0.0) x->b2 = 0.9999998 + x->b1; } } //post("double a0=%f, a1=%f, a2=%f, b1=%f, b2=%f", (t_float)x->a0, (t_float)x->a1, (t_float)x->a2, (t_float)x->b1, (t_float)x->b2); } } static t_int *filter_tilde_sp_perform_2o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); t_float wn0, wn1=x->x_para.sp.wn1, wn2=x->x_para.sp.wn2; t_float a0=x->x_para.sp.a0, a1=x->x_para.sp.a1, a2=x->x_para.sp.a2; t_float b1=x->x_para.sp.b1, b2=x->x_para.sp.b2; filter_tilde_dsp_sp_tick(&x->x_para.sp); for(i=0; ix_para.sp.wn1 = wn1; x->x_para.sp.wn2 = wn2; return(w+5); } /* yn0 = *out; xn0 = *in; ************* yn0 = a0*xn0 + a1*xn1 + a2*xn2 + b1*yn1 + b2*yn2; yn2 = yn1; yn1 = yn0; xn2 = xn1; xn1 = xn0; ************************* y/x = (a0 + a1*z-1 + a2*z-2)/(1 - b1*z-1 - b2*z-2);*/ static t_int *filter_tilde_sp_perf8_2o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); t_float wn[10]; t_float a0=x->x_para.sp.a0, a1=x->x_para.sp.a1, a2=x->x_para.sp.a2; t_float b1=x->x_para.sp.b1, b2=x->x_para.sp.b2; filter_tilde_dsp_sp_tick(&x->x_para.sp); wn[0] = x->x_para.sp.wn2; wn[1] = x->x_para.sp.wn1; for(i=0; ix_para.sp.wn1 = wn[1]; x->x_para.sp.wn2 = wn[0]; return(w+5); } static t_int *filter_tilde_sp_perform_1o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); t_float wn0, wn1=x->x_para.sp.wn1; t_float a0=x->x_para.sp.a0, a1=x->x_para.sp.a1; t_float b1=x->x_para.sp.b1; filter_tilde_dsp_sp_tick(&x->x_para.sp); for(i=0; ix_para.sp.wn1 = wn1; return(w+5); } static t_int *filter_tilde_sp_perf8_1o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); t_float wn[9]; t_float a0=x->x_para.sp.a0, a1=x->x_para.sp.a1; t_float b1=x->x_para.sp.b1; filter_tilde_dsp_sp_tick(&x->x_para.sp); wn[0] = x->x_para.sp.wn1; for(i=0; ix_para.sp.wn1 = wn[0]; return(w+5); } static t_int *filter_tilde_dp_perform_2o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); double wn0, wn1=x->x_para.dp.wn1, wn2=x->x_para.dp.wn2; double a0=x->x_para.dp.a0, a1=x->x_para.dp.a1, a2=x->x_para.dp.a2; double b1=x->x_para.dp.b1, b2=x->x_para.dp.b2; filter_tilde_dsp_dp_tick(&x->x_para.dp); for(i=0; ix_para.dp.wn1 = wn1; x->x_para.dp.wn2 = wn2; return(w+5); } /* yn0 = *out; xn0 = *in; ************* yn0 = a0*xn0 + a1*xn1 + a2*xn2 + b1*yn1 + b2*yn2; yn2 = yn1; yn1 = yn0; xn2 = xn1; xn1 = xn0; ************************* y/x = (a0 + a1*z-1 + a2*z-2)/(1 - b1*z-1 - b2*z-2);*/ static t_int *filter_tilde_dp_perf8_2o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); double wn[10]; double a0=x->x_para.dp.a0, a1=x->x_para.dp.a1, a2=x->x_para.dp.a2; double b1=x->x_para.dp.b1, b2=x->x_para.dp.b2; filter_tilde_dsp_dp_tick(&x->x_para.dp); wn[0] = x->x_para.dp.wn2; wn[1] = x->x_para.dp.wn1; for(i=0; ix_para.dp.wn1 = wn[1]; x->x_para.dp.wn2 = wn[0]; return(w+5); } static t_int *filter_tilde_dp_perform_1o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); double wn0, wn1=x->x_para.dp.wn1; double a0=x->x_para.dp.a0, a1=x->x_para.dp.a1; double b1=x->x_para.dp.b1; filter_tilde_dsp_dp_tick(&x->x_para.dp); for(i=0; ix_para.dp.wn1 = wn1; return(w+5); } static t_int *filter_tilde_dp_perf8_1o(t_int *w) { t_sample *in = (t_sample *)(w[1]); t_sample *out = (t_sample *)(w[2]); t_filter_tilde *x = (t_filter_tilde *)(w[3]); int i, n = (t_int)(w[4]); double wn[9]; double a0=x->x_para.dp.a0, a1=x->x_para.dp.a1; double b1=x->x_para.dp.b1; filter_tilde_dsp_dp_tick(&x->x_para.dp); wn[0] = x->x_para.dp.wn1; for(i=0; ix_para.dp.wn1 = wn[0]; return(w+5); } static void filter_tilde_ft4(t_filter_tilde *x, t_floatarg t) { if(x->x_precision_dp1_sp0) { double dt = (double)t; int di = (int)((x->x_para.dp.ticks_per_interpol_time)*dt+0.49999); x->x_para.dp.interpol_time = dt; if(di <= 0) { x->x_para.dp.ticks = 1; x->x_para.dp.rcp_ticks = 1.0; } else { x->x_para.dp.ticks = di; x->x_para.dp.rcp_ticks = 1.0 / (double)di; } } else { t_float st = (t_float)t; int i = (int)((x->x_para.sp.ticks_per_interpol_time)*st+0.49999f); x->x_para.sp.interpol_time = st; if(i <= 0) { x->x_para.sp.ticks = 1; x->x_para.sp.rcp_ticks = 1.0f; } else { x->x_para.sp.ticks = i; x->x_para.sp.rcp_ticks = 1.0f / (t_float)i; } } } static void filter_tilde_ft3(t_filter_tilde *x, t_floatarg b) { if(x->x_precision_dp1_sp0) { double db = (double)b; if(db <= 0.0) db = 0.000001; if(x->x_para.dp.filter_function_is_highpass) db = 1.0 / db; if(db != x->x_para.dp.cur_b) { x->x_para.dp.end_b = db; x->x_para.dp.counter_b = x->x_para.dp.ticks; x->x_para.dp.delta_b = exp(log(db/x->x_para.dp.cur_b)*x->x_para.dp.rcp_ticks); x->x_para.dp.event_mask |= 4;/*set event_mask_bit 2 = 1*/ } } else { t_float sb = (t_float)b; if(sb <= 0.0f) sb = 0.000001f; if(x->x_para.sp.filter_function_is_highpass) sb = 1.0f / sb; if(sb != x->x_para.sp.cur_b) { x->x_para.sp.end_b = sb; x->x_para.sp.counter_b = x->x_para.sp.ticks; x->x_para.sp.delta_b = exp(log(sb/x->x_para.sp.cur_b)*x->x_para.sp.rcp_ticks); x->x_para.sp.event_mask |= 4;/*set event_mask_bit 2 = 1*/ } } } static void filter_tilde_ft2(t_filter_tilde *x, t_floatarg a) { if(x->x_precision_dp1_sp0) { double da = (double)a; if(da <= 0.0) da = 0.000001; if(x->x_para.dp.inlet3_is_Q) da = 1.0 / da; if(x->x_para.dp.filter_function_is_highpass) da /= x->x_para.dp.cur_b; if(da != x->x_para.dp.cur_a) { x->x_para.dp.end_a = da; x->x_para.dp.counter_a = x->x_para.dp.ticks; x->x_para.dp.delta_a = exp(log(da/x->x_para.dp.cur_a)*x->x_para.dp.rcp_ticks); x->x_para.dp.event_mask |= 2;/*set event_mask_bit 1 = 1*/ } } else { t_float sa = (t_float)a; if(sa <= 0.0f) sa = 0.000001f; if(x->x_para.sp.inlet3_is_Q) sa = 1.0f / sa; if(x->x_para.sp.filter_function_is_highpass) sa /= x->x_para.sp.cur_b; if(sa != x->x_para.sp.cur_a) { x->x_para.sp.end_a = sa; x->x_para.sp.counter_a = x->x_para.sp.ticks; x->x_para.sp.delta_a = exp(log(sa/x->x_para.sp.cur_a)*x->x_para.sp.rcp_ticks); x->x_para.sp.event_mask |= 2;/*set event_mask_bit 1 = 1*/ } } } static void filter_tilde_ft1(t_filter_tilde *x, t_floatarg f) { if(x->x_precision_dp1_sp0) { double df = (double)f; if(df <= 0.0) df = 0.000001; if(df != x->x_para.dp.cur_f) { x->x_para.dp.end_f = df; x->x_para.dp.counter_f = x->x_para.dp.ticks; x->x_para.dp.delta_f = exp(log(df/x->x_para.dp.cur_f)*x->x_para.dp.rcp_ticks); x->x_para.dp.event_mask |= 1;/*set event_mask_bit 0 = 1*/ } } else { t_float sf = (t_float)f; if(sf <= 0.0f) sf = 0.000001f; if(sf != x->x_para.sp.cur_f) { x->x_para.sp.end_f = sf; x->x_para.sp.counter_f = x->x_para.sp.ticks; x->x_para.sp.delta_f = exp(log(sf/x->x_para.sp.cur_f)*x->x_para.sp.rcp_ticks); x->x_para.sp.event_mask |= 1;/*set event_mask_bit 0 = 1*/ } } } static void filter_tilde_print(t_filter_tilde *x) { // post("fb1 = %g, fb2 = %g, ff1 = %g, ff2 = %g, ff3 = %g", x->b1, x->b2, x->a0, x->a1, x->a2); if(x->x_precision_dp1_sp0) { x->x_at[0].a_w.w_float = (t_float)x->x_para.dp.b1; x->x_at[1].a_w.w_float = (t_float)x->x_para.dp.b2; x->x_at[2].a_w.w_float = (t_float)x->x_para.dp.a0; x->x_at[3].a_w.w_float = (t_float)x->x_para.dp.a1; x->x_at[4].a_w.w_float = (t_float)x->x_para.dp.a2; } else { x->x_at[0].a_w.w_float = x->x_para.sp.b1; x->x_at[1].a_w.w_float = x->x_para.sp.b2; x->x_at[2].a_w.w_float = x->x_para.sp.a0; x->x_at[3].a_w.w_float = x->x_para.sp.a1; x->x_at[4].a_w.w_float = x->x_para.sp.a2; } outlet_list(x->x_debug_outlet, &s_list, 5, x->x_at); } static void filter_tilde_set(t_filter_tilde *x, t_symbol *s, int argc, t_atom *argv) { if((argc >= 1) && IS_A_FLOAT(argv, 0)) { if(x->x_precision_dp1_sp0) x->x_para.dp.wn1 = (double)atom_getfloatarg(0, argc, argv); else x->x_para.sp.wn1 = (t_float)atom_getfloatarg(0, argc, argv); } if((argc >= 2) && IS_A_FLOAT(argv, 1) && (x->x_para.dp.filter_function_is_first_order == 0)) { if(x->x_precision_dp1_sp0) x->x_para.dp.wn2 = (double)atom_getfloatarg(1, argc, argv); else x->x_para.sp.wn2 = (t_float)atom_getfloatarg(1, argc, argv); } } static void filter_tilde_dsp(t_filter_tilde *x, t_signal **sp) { int i, n=(int)sp[0]->s_n; if(x->x_precision_dp1_sp0) { double si, co, f; x->x_para.dp.pi_over_sr = 3.14159265358979323846 / (double)(sp[0]->s_sr); x->x_para.dp.ticks_per_interpol_time = 0.001 * (double)(sp[0]->s_sr) / (double)n; i = (int)((x->x_para.dp.ticks_per_interpol_time)*(x->x_para.dp.interpol_time)+0.49999); if(i <= 0) { x->x_para.dp.ticks = 1; x->x_para.dp.rcp_ticks = 1.0; } else { x->x_para.dp.ticks = i; x->x_para.dp.rcp_ticks = 1.0 / (double)i; } f = x->x_para.dp.cur_f * x->x_para.dp.pi_over_sr; if(f < 1.0e-20) x->x_para.dp.cur_l = 1.0e20; else if(f > 1.57079632) x->x_para.dp.cur_l = 0.0; else { si = sin(f); co = cos(f); x->x_para.dp.cur_l = co/si; } if(x->x_para.dp.filter_function_is_first_order) { if(n&7) dsp_add(filter_tilde_dp_perform_1o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); else dsp_add(filter_tilde_dp_perf8_1o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); } else { if(n&7) dsp_add(filter_tilde_dp_perform_2o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); else dsp_add(filter_tilde_dp_perf8_2o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); } } else { t_float si, co, f; x->x_para.sp.pi_over_sr = 3.14159265358979323846f / (t_float)(sp[0]->s_sr); x->x_para.sp.ticks_per_interpol_time = 0.001f * (t_float)(sp[0]->s_sr) / (t_float)n; i = (int)((x->x_para.sp.ticks_per_interpol_time)*(x->x_para.sp.interpol_time)+0.49999f); if(i <= 0) { x->x_para.sp.ticks = 1; x->x_para.sp.rcp_ticks = 1.0f; } else { x->x_para.sp.ticks = i; x->x_para.sp.rcp_ticks = 1.0f / (t_float)i; } f = x->x_para.sp.cur_f * x->x_para.sp.pi_over_sr; if(f < 1.0e-20f) x->x_para.sp.cur_l = 1.0e20f; else if(f > 1.57079632f) x->x_para.sp.cur_l = 0.0f; else { si = sin(f); co = cos(f); x->x_para.sp.cur_l = co/si; } if(x->x_para.sp.filter_function_is_first_order) { if(n&7) dsp_add(filter_tilde_sp_perform_1o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); else dsp_add(filter_tilde_sp_perf8_1o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); } else { if(n&7) dsp_add(filter_tilde_sp_perform_2o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); else dsp_add(filter_tilde_sp_perf8_2o, 4, sp[0]->s_vec, sp[1]->s_vec, x, n); } } } static void *filter_tilde_new(t_symbol *s, int argc, t_atom *argv) { t_filter_tilde *x = (t_filter_tilde *)pd_new(filter_tilde_class); int i; t_symbol *filt_typ=gensym(""); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft2")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft3")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft4")); outlet_new(&x->x_obj, &s_signal); x->x_debug_outlet = outlet_new(&x->x_obj, &s_list); x->x_float_sig_in = 0.0f; x->x_at[0].a_type = A_FLOAT; x->x_at[1].a_type = A_FLOAT; x->x_at[2].a_type = A_FLOAT; x->x_at[3].a_type = A_FLOAT; x->x_at[4].a_type = A_FLOAT; x->x_para.dp.delta_f = 0.0; x->x_para.dp.delta_a = 0.0; x->x_para.dp.delta_b = 0.0; x->x_para.dp.interpol_time = 0.0; x->x_para.dp.wn1 = 0.0; x->x_para.dp.wn2 = 0.0; x->x_para.dp.a0 = 0.0; x->x_para.dp.a1 = 0.0; x->x_para.dp.a2 = 0.0; x->x_para.dp.b1 = 0.0; x->x_para.dp.b2 = 0.0; x->x_para.dp.pi_over_sr = 3.14159265358979323846 / 44100.0; x->x_para.dp.event_mask = 1; x->x_para.dp.counter_f = 1; x->x_para.dp.counter_a = 0; x->x_para.dp.counter_b = 0; x->x_para.dp.filter_function_is_first_order = 0; x->x_para.sp.delta_f = 0.0f; x->x_para.sp.delta_a = 0.0f; x->x_para.sp.delta_b = 0.0f; x->x_para.sp.interpol_time = 0.0f; x->x_para.sp.wn1 = 0.0f; x->x_para.sp.wn2 = 0.0f; x->x_para.sp.a0 = 0.0f; x->x_para.sp.a1 = 0.0f; x->x_para.sp.a2 = 0.0f; x->x_para.sp.b1 = 0.0f; x->x_para.sp.b2 = 0.0f; x->x_para.sp.pi_over_sr = 3.14159265358979323846f / 44100.0f; x->x_para.sp.event_mask = 1; x->x_para.sp.counter_f = 1; x->x_para.sp.counter_a = 0; x->x_para.sp.counter_b = 0; x->x_para.sp.filter_function_is_first_order = 0; if((argc >= 1) && IS_A_SYMBOL(argv,0)) filt_typ = atom_getsymbolarg(0, argc, argv); if(filt_typ->s_name[0] == 'd') x->x_precision_dp1_sp0 = 1; else x->x_precision_dp1_sp0 = 0; if(x->x_precision_dp1_sp0) { double si, co, f=0.0, a=0.0, b=0.0, interpol=0.0; if((argc >= 5) && IS_A_FLOAT(argv,4) && IS_A_FLOAT(argv,3) && IS_A_FLOAT(argv,2) && IS_A_FLOAT(argv,1)) { f = (double)atom_getfloatarg(1, argc, argv); a = (double)atom_getfloatarg(2, argc, argv); b = (double)atom_getfloatarg(3, argc, argv); interpol = (double)atom_getfloatarg(4, argc, argv); } x->x_para.dp.cur_f = f; f *= x->x_para.dp.pi_over_sr; if(f < 1.0e-20) x->x_para.dp.cur_l = 1.0e20; else if(f > 1.57079632) x->x_para.dp.cur_l = 0.0; else { si = sin(f); co = cos(f); x->x_para.dp.cur_l = co/si; } if(a <= 0.0) a = 0.000001; if(b <= 0.0) b = 0.000001; if(interpol <= 0.0) interpol = 0.0; x->x_para.dp.interpol_time = interpol; x->x_para.dp.ticks_per_interpol_time = 0.001 * 44100.0 / 64.0; i = (int)((x->x_para.dp.ticks_per_interpol_time)*(x->x_para.dp.interpol_time)+0.49999); if(i <= 0) { x->x_para.dp.ticks = 1; x->x_para.dp.rcp_ticks = 1.0; } else { x->x_para.dp.ticks = i; x->x_para.dp.rcp_ticks = 1.0 / (double)i; } x->x_para.dp.cur_b = b; x->x_para.dp.cur_a = 1.0/a; /*"a" is default Q*/ x->x_para.dp.inlet3_is_Q = 1; x->x_para.dp.filter_function_is_highpass = 0; x->x_para.dp.calc = filter_tilde_dp_dummy; if(filt_typ->s_name) { if(filt_typ == gensym("dap1")) { x->x_para.dp.calc = filter_tilde_dp_ap1; x->x_para.dp.a1 = 1.0; x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dap2")) { x->x_para.dp.calc = filter_tilde_dp_ap2; x->x_para.dp.a2 = 1.0; } else if(filt_typ == gensym("dap1c")) { x->x_para.dp.calc = filter_tilde_dp_ap1; x->x_para.dp.a1 = 1.0; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was damping*/ x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dap2c")) { x->x_para.dp.calc = filter_tilde_dp_ap2; x->x_para.dp.a2 = 1.0; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was damping*/ } else if(filt_typ == gensym("dbpq2")) { x->x_para.dp.calc = filter_tilde_dp_bp2; } else if(filt_typ == gensym("drbpq2")) { x->x_para.dp.calc = filter_tilde_dp_rp2; } else if(filt_typ == gensym("dbsq2")) { x->x_para.dp.calc = filter_tilde_dp_bs2; } else if(filt_typ == gensym("dbpw2")) { x->x_para.dp.calc = filter_tilde_dp_bpw2; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("drbpw2")) { x->x_para.dp.calc = filter_tilde_dp_rpw2; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("dbsw2")) { x->x_para.dp.calc = filter_tilde_dp_bsw2; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("dhp1")) { x->x_para.dp.calc = filter_tilde_dp_hp1; x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dhp2")) { x->x_para.dp.calc = filter_tilde_dp_hp2; } else if(filt_typ == gensym("dlp1")) { x->x_para.dp.calc = filter_tilde_dp_lp1; x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dlp2")) { x->x_para.dp.calc = filter_tilde_dp_lp2; } else if(filt_typ == gensym("dhp1c")) { x->x_para.dp.calc = filter_tilde_dp_hp1; x->x_para.dp.cur_a = 1.0 / a; x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dhp2c")) { x->x_para.dp.calc = filter_tilde_dp_hp2; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a / b; x->x_para.dp.cur_b = 1.0 / b; x->x_para.dp.filter_function_is_highpass = 1; } else if(filt_typ == gensym("dlp1c")) { x->x_para.dp.calc = filter_tilde_dp_lp1; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was damping*/ x->x_para.dp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("dlp2c")) { x->x_para.dp.calc = filter_tilde_dp_lp2; x->x_para.dp.inlet3_is_Q = 0; x->x_para.dp.cur_a = a; /*"a" was damping*/ } else { post("filter~-Error: 1. initial-arguments: kind: \ lp1, lp2, hp1, hp2, \ lp1c, lp2c, hp1c, hp2c, \ ap1, ap2, ap1c, ap2c, \ bpq2, rbpq2, bsq2, \ bpw2, rbpw2, bsw2, \ dlp1, dlp2, dhp1, dhp2, \ dlp1c, dlp2c, dhp1c, dhp2c, \ dap1, dap2, dap1c, dap2c, \ dbpq2, drbpq2, dbsq2, \ dbpw2, drbpw2, dbsw2 !"); } x->x_para.dp.end_f = x->x_para.dp.cur_f; x->x_para.dp.end_a = x->x_para.dp.cur_a; x->x_para.dp.end_b = x->x_para.dp.cur_b; } } else { t_float si, co, f=0.0f, a=0.0f, b=0.0f, interpol=0.0f; if((argc >= 5) && IS_A_FLOAT(argv,4) && IS_A_FLOAT(argv,3) && IS_A_FLOAT(argv,2) && IS_A_FLOAT(argv,1)) { f = (t_float)atom_getfloatarg(1, argc, argv); a = (t_float)atom_getfloatarg(2, argc, argv); b = (t_float)atom_getfloatarg(3, argc, argv); interpol = (t_float)atom_getfloatarg(4, argc, argv); } x->x_para.sp.cur_f = f; f *= x->x_para.sp.pi_over_sr; if(f < 1.0e-20f) x->x_para.sp.cur_l = 1.0e20f; else if(f > 1.57079632f) x->x_para.sp.cur_l = 0.0f; else { si = sin(f); co = cos(f); x->x_para.sp.cur_l = co/si; } if(a <= 0.0f) a = 0.000001f; if(b <= 0.0f) b = 0.000001f; if(interpol <= 0.0f) interpol = 0.0f; x->x_para.sp.interpol_time = interpol; x->x_para.sp.ticks_per_interpol_time = 0.001f * 44100.0f / 64.0f; i = (int)((x->x_para.sp.ticks_per_interpol_time)*(x->x_para.sp.interpol_time)+0.49999f); if(i <= 0) { x->x_para.sp.ticks = 1; x->x_para.sp.rcp_ticks = 1.0f; } else { x->x_para.sp.ticks = i; x->x_para.sp.rcp_ticks = 1.0f / (t_float)i; } x->x_para.sp.cur_b = b; x->x_para.sp.cur_a = 1.0f/a; /*"a" is default Q*/ x->x_para.sp.inlet3_is_Q = 1; x->x_para.sp.filter_function_is_highpass = 0; x->x_para.sp.calc = filter_tilde_sp_dummy; if(filt_typ->s_name) { if(filt_typ == gensym("ap1")) { x->x_para.sp.calc = filter_tilde_sp_ap1; x->x_para.sp.a1 = 1.0f; x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("ap2")) { x->x_para.sp.calc = filter_tilde_sp_ap2; x->x_para.sp.a2 = 1.0f; } else if(filt_typ == gensym("ap1c")) { x->x_para.sp.calc = filter_tilde_sp_ap1; x->x_para.sp.a1 = 1.0f; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was damping*/ x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("ap2c")) { x->x_para.sp.calc = filter_tilde_sp_ap2; x->x_para.sp.a2 = 1.0f; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was damping*/ } else if(filt_typ == gensym("bpq2")) { x->x_para.sp.calc = filter_tilde_sp_bp2; } else if(filt_typ == gensym("rbpq2")) { x->x_para.sp.calc = filter_tilde_sp_rp2; } else if(filt_typ == gensym("bsq2")) { x->x_para.sp.calc = filter_tilde_sp_bs2; } else if(filt_typ == gensym("bpw2")) { x->x_para.sp.calc = filter_tilde_sp_bpw2; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("rbpw2")) { x->x_para.sp.calc = filter_tilde_sp_rpw2; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("bsw2")) { x->x_para.sp.calc = filter_tilde_sp_bsw2; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was bw*/ } else if(filt_typ == gensym("hp1")) { x->x_para.sp.calc = filter_tilde_sp_hp1; x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("hp2")) { x->x_para.sp.calc = filter_tilde_sp_hp2; } else if(filt_typ == gensym("lp1")) { x->x_para.sp.calc = filter_tilde_sp_lp1; x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("lp2")) { x->x_para.sp.calc = filter_tilde_sp_lp2; } else if(filt_typ == gensym("hp1c")) { x->x_para.sp.calc = filter_tilde_sp_hp1; x->x_para.sp.cur_a = 1.0f / a; x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("hp2c")) { x->x_para.sp.calc = filter_tilde_sp_hp2; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a / b; x->x_para.sp.cur_b = 1.0f / b; x->x_para.sp.filter_function_is_highpass = 1; } else if(filt_typ == gensym("lp1c")) { x->x_para.sp.calc = filter_tilde_sp_lp1; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was damping*/ x->x_para.sp.filter_function_is_first_order = 1; } else if(filt_typ == gensym("lp2c")) { x->x_para.sp.calc = filter_tilde_sp_lp2; x->x_para.sp.inlet3_is_Q = 0; x->x_para.sp.cur_a = a; /*"a" was damping*/ } else { post("filter~-Error: 1. initial-arguments: kind: \ lp1, lp2, hp1, hp2, \ lp1c, lp2c, hp1c, hp2c, \ ap1, ap2, ap1c, ap2c, \ bpq2, rbpq2, bsq2, \ bpw2, rbpw2, bsw2, \ dlp1, dlp2, dhp1, dhp2, \ dlp1c, dlp2c, dhp1c, dhp2c, \ dap1, dap2, dap1c, dap2c, \ dbpq2, drbpq2, dbsq2, \ dbpw2, drbpw2, dbsw2 !"); } x->x_para.sp.end_f = x->x_para.sp.cur_f; x->x_para.sp.end_a = x->x_para.sp.cur_a; x->x_para.sp.end_b = x->x_para.sp.cur_b; } } return (x); } void filter_tilde_setup(void) { filter_tilde_class = class_new(gensym("filter~"), (t_newmethod)filter_tilde_new, 0, sizeof(t_filter_tilde), 0, A_GIMME, 0); CLASS_MAINSIGNALIN(filter_tilde_class, t_filter_tilde, x_float_sig_in); class_addmethod(filter_tilde_class, (t_method)filter_tilde_dsp, gensym("dsp"), 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_ft1, gensym("ft1"), A_FLOAT, 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_ft2, gensym("ft2"), A_FLOAT, 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_ft3, gensym("ft3"), A_FLOAT, 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_ft4, gensym("ft4"), A_FLOAT, 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_set, gensym("set"), A_GIMME, 0); class_addmethod(filter_tilde_class, (t_method)filter_tilde_print, gensym("print"), 0); }