diff options
-rw-r--r-- | iemlib1/sparse_FIR~-help.pd | 88 | ||||
-rw-r--r-- | iemlib1/src/sparse_FIR~.c | 223 |
2 files changed, 311 insertions, 0 deletions
diff --git a/iemlib1/sparse_FIR~-help.pd b/iemlib1/sparse_FIR~-help.pd new file mode 100644 index 0000000..3eb7ba2 --- /dev/null +++ b/iemlib1/sparse_FIR~-help.pd @@ -0,0 +1,88 @@ +#N canvas 156 22 842 608 10; +#X floatatom 4 133 5 0 0 0 - - -; +#X text 32 96 % cpu; +#X obj 4 93 dsp; +#X obj 4 73 tgl 15 0 empty empty dsp_ON/OFF 2 -8 0 10 -225271 -42246 +-90881 1 1; +#X floatatom 183 494 7 0 0 0 - - -; +#X obj 112 373 dac~; +#X obj 112 347 gainvu~ 300; +#X obj 174 369 vu 15 120 empty empty 8 -8 0 10 -66577 -1 1 0; +#X obj 294 216 vsl 15 128 0 127 0 1 empty empty gain -7 -8 0 10 -225271 +-42246 -90881 7500 1; +#X obj 113 95 noise~; +#X floatatom 173 512 7 0 0 0 - - -; +#X floatatom 17 113 5 0 0 0 - - -; +#X text 170 567 IEM KUG; +#X text 146 555 musil; +#X text 182 555 @; +#X text 190 555 iem.at; +#X text 153 577 Graz \, Austria; +#X floatatom 142 323 5 0 0 0 - - -; +#X obj 113 179 sparse_FIR~ 256; +#X msg 177 112 size 256; +#X msg 367 535 0 1 1 1; +#X msg 367 556 0 1 40 -1 80 1 120 -1 160 1; +#X msg 369 312 0 1 10 1 20 1 30 1 40 1 50 1 60 1 70 1 80 1; +#X obj 707 38 t b b; +#X msg 767 101 set; +#X msg 668 101 add2 \$1 \$2; +#X obj 707 18 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1 +-1; +#X msg 176 137 order 384; +#X msg 366 342 matrix 9 2 0 1 10 1 20 1 30 1 40 1 50 1 60 1 70 1 80 +1; +#X msg 363 371 matrix 2 9 0 1 10 1 20 1 30 1 40 1 50 1 60 1 70 1 80 +1; +#X text 103 544 (c) Thomas Musil 2000 - 2010; +#X text 17 16 sparse_FIR~; +#X msg 370 581 0 0; +#X msg 370 502 0 -0.1 1 -0.18 2 -0.1 3 0.15 4 0.4 5 0.7 6 0.4 7 0.15 +8 -0.1 9 -0.18 10 -0.1; +#X msg 510 126 0 0.04 1 0.04 2 0.04 3 0.04 4 0.04 5 0.04 6 0.04 7 0.04 +8 0.04 9 0.04 10 0.04 11 0.04 12 0.04 13 0.04 14 0.04 15 0.04 16 0.04 +17 0.04 18 0.04 19 0.04 20 0.04 21 0.04 22 0.04 23 0.04 24 0.04 25 +0.04 26 0.04 27 0.04 28 0.04 29 0.04; +#X obj 668 81 pack 0 0.04; +#X obj 668 59 for++ 0 29; +#X text 366 228 A list of alternating index- and value- doubles will +change the coefficients of convolution. The number of pairs should +be less than the order of FIR.; +#X text 367 276 A matrix message will do the same.; +#X obj 568 93 loadbang; +#X text 134 16 convolve a signal with a coefficent list of non zero +index/value pairs. All values between the determined values will be +set to zero and won't be calculated (sparse).; +#X text 227 182 1.arg: <float> maximum convolution-length or order +; +#X text 176 93 will change the max. order of FIR filter.; +#X connect 2 0 0 0; +#X connect 2 1 11 0; +#X connect 3 0 2 0; +#X connect 6 0 5 0; +#X connect 6 0 5 1; +#X connect 6 1 17 0; +#X connect 6 2 7 0; +#X connect 7 0 10 0; +#X connect 7 1 4 0; +#X connect 8 0 6 1; +#X connect 9 0 18 0; +#X connect 18 0 6 0; +#X connect 19 0 18 0; +#X connect 20 0 18 0; +#X connect 21 0 18 0; +#X connect 22 0 18 0; +#X connect 23 0 36 0; +#X connect 23 1 24 0; +#X connect 24 0 34 0; +#X connect 25 0 34 0; +#X connect 26 0 23 0; +#X connect 27 0 18 0; +#X connect 28 0 18 0; +#X connect 29 0 18 0; +#X connect 32 0 18 0; +#X connect 33 0 18 0; +#X connect 34 0 18 0; +#X connect 35 0 25 0; +#X connect 36 0 35 0; +#X connect 39 0 34 0; diff --git a/iemlib1/src/sparse_FIR~.c b/iemlib1/src/sparse_FIR~.c new file mode 100644 index 0000000..0a1043a --- /dev/null +++ b/iemlib1/src/sparse_FIR~.c @@ -0,0 +1,223 @@ +/* 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 - 2010 */ + + +#include "m_pd.h" +#include "iemlib.h" + + +/* ---------- sparse_FIR~ - sparse_FIR-filter with coef-matrix-message ----------- */ +/* the list or matrix message should have an index and its value, index , value, aso.... */ + +typedef struct _sparse_FIR_tilde +{ + t_object x_obj; + t_float *x_coef_beg; + int *x_index_beg; + int x_n_coef; + int x_n_coef_malloc; + t_float *x_history_beg; + int x_rw_index; + int x_sparse_FIR_order; + t_float x_msi; +} t_sparse_FIR_tilde; + +static t_class *sparse_FIR_tilde_class; + +static t_int *sparse_FIR_tilde_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + t_sparse_FIR_tilde *x = (t_sparse_FIR_tilde *)(w[3]); + int n = (t_int)(w[4]); + int rw_index = x->x_rw_index; + int i, j, ix; + int order = x->x_sparse_FIR_order; + int n_coef = x->x_n_coef; + int n_coef8; + t_float sum=0.0f; + t_float *coef = x->x_coef_beg; + int *index = x->x_index_beg; + t_float *write_hist1=x->x_history_beg; + t_float *write_hist2; + t_float *read_hist; + t_float *coef_vec; + int *index_vec; + t_float *hist_vec; + + if((order < 1) || (n_coef < 1)) + goto sparse_FIR_tilde_perf_zero; + + n_coef8 = n_coef / 8; + write_hist1 = x->x_history_beg; + write_hist2 = write_hist1 + order; + read_hist = write_hist2; + + for(i=0; i<n; i++) + { + write_hist1[rw_index] = in[i]; + write_hist2[rw_index] = in[i]; + sum = 0.0f; + coef_vec = coef; + index_vec = index; + hist_vec = &read_hist[rw_index]; + for(j=0; j<n_coef8; j++) + { + ix = index_vec[0]; + sum += coef_vec[0] * hist_vec[ix]; + ix = index_vec[1]; + sum += coef_vec[1] * hist_vec[ix]; + ix = index_vec[2]; + sum += coef_vec[2] * hist_vec[ix]; + ix = index_vec[3]; + sum += coef_vec[3] * hist_vec[ix]; + ix = index_vec[4]; + sum += coef_vec[4] * hist_vec[ix]; + ix = index_vec[5]; + sum += coef_vec[5] * hist_vec[ix]; + ix = index_vec[6]; + sum += coef_vec[6] * hist_vec[ix]; + ix = index_vec[7]; + sum += coef_vec[7] * hist_vec[ix]; + coef_vec += 8; + index_vec += 8; + } + for(j=n_coef8*8; j<n_coef; j++) + { + ix = index[j]; + sum += coef[j] * read_hist[rw_index+ix]; + } + out[i] = sum; + rw_index++; + if(rw_index >= order) + rw_index -= order; + } + + x->x_rw_index = rw_index; + return(w+5); + +sparse_FIR_tilde_perf_zero: + + while(n--) + *out++ = 0.0f; + return(w+5); +} + +static void sparse_FIR_tilde_list(t_sparse_FIR_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int order = x->x_sparse_FIR_order; + int n_arg2 = argc/2, index, i; + int n_coef = 0; + int *index_pointer = x->x_index_beg; + t_float *coef_pointer = x->x_coef_beg; + t_float coef; + + for(i=0; i<n_arg2; i++) + { + index = (int)atom_getfloat(argv++); + coef = (t_float)atom_getfloat(argv++); + if((index >= 0) && (index < order)) + { + *index_pointer++ = -index; + *coef_pointer++ = coef; + n_coef++; + } + } + x->x_n_coef = n_coef; +} + +static void sparse_FIR_tilde_matrix(t_sparse_FIR_tilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col; + + if(argc < 2) + { + post("sparse_FIR~ : corrupt matrix passed"); + return; + } + row = (int)atom_getfloat(argv++); + col = (int)atom_getfloat(argv++); + if((row < 1)||(col < 1)) + { + post("sparse_FIR~ : corrupt matrix passed"); + return; + } + if((row*col) < (argc - 2)) + { + post("sparse_FIR~ WARNING: row column product less than message content!"); + sparse_FIR_tilde_list(x, &s_list, row*col, argv); + } + else if((row*col) > (argc-2)) + { + post("sparse_FIR~ WARNING: row column product greater than message content!"); + sparse_FIR_tilde_list(x, &s_list, argc-2, argv); + } + else + sparse_FIR_tilde_list(x, &s_list, argc-2, argv); +} + +static void sparse_FIR_tilde_order(t_sparse_FIR_tilde *x, t_floatarg fn) +{ + int n = (int)fn; + + if(n > 0) + { + if(n > x->x_sparse_FIR_order)/* resize */ + { + x->x_history_beg = (t_float *)resizebytes(x->x_history_beg, 2*x->x_n_coef_malloc*sizeof(t_float), 2*n*sizeof(t_float)); + x->x_index_beg = (int *)resizebytes(x->x_index_beg, x->x_n_coef_malloc*sizeof(int), n*sizeof(int)); + x->x_coef_beg = (t_float *)resizebytes(x->x_coef_beg, x->x_n_coef_malloc*sizeof(t_float), n*sizeof(t_float)); + x->x_n_coef_malloc = n; + } + x->x_sparse_FIR_order = n; + x->x_rw_index = 0; + } +} + +static void sparse_FIR_tilde_dsp(t_sparse_FIR_tilde *x, t_signal **sp) +{ + dsp_add(sparse_FIR_tilde_perform, 4, sp[0]->s_vec, sp[1]->s_vec, x, sp[0]->s_n); +} + +static void *sparse_FIR_tilde_new(t_floatarg fn) +{ + t_sparse_FIR_tilde *x = (t_sparse_FIR_tilde *)pd_new(sparse_FIR_tilde_class); + int n=(int)fn; + + outlet_new(&x->x_obj, &s_signal); + x->x_msi = 0; + x->x_n_coef = 0; + if(n < 1) + n = 1; + x->x_sparse_FIR_order = n; + x->x_n_coef_malloc = n; + x->x_history_beg = (t_float *)getbytes((2*x->x_n_coef_malloc)*sizeof(t_float)); + x->x_index_beg = (int *)getbytes(x->x_n_coef_malloc*sizeof(int)); + x->x_coef_beg = (t_float *)getbytes(x->x_n_coef_malloc*sizeof(t_float)); + x->x_rw_index = 0; + return(x); +} + +static void sparse_FIR_tilde_free(t_sparse_FIR_tilde *x) +{ + if(x->x_history_beg) + freebytes(x->x_history_beg, (2*x->x_n_coef_malloc)*sizeof(t_float)); + if(x->x_index_beg) + freebytes(x->x_index_beg, x->x_n_coef_malloc*sizeof(int)); + if(x->x_coef_beg) + freebytes(x->x_coef_beg, x->x_n_coef_malloc*sizeof(t_float)); +} + +void sparse_FIR_tilde_setup(void) +{ + sparse_FIR_tilde_class = class_new(gensym("sparse_FIR~"), (t_newmethod)sparse_FIR_tilde_new, + (t_method)sparse_FIR_tilde_free, sizeof(t_sparse_FIR_tilde), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sparse_FIR_tilde_class, t_sparse_FIR_tilde, x_msi); + class_addmethod(sparse_FIR_tilde_class, (t_method)sparse_FIR_tilde_dsp, gensym("dsp"), 0); + class_addlist(sparse_FIR_tilde_class, (t_method)sparse_FIR_tilde_list); + class_addmethod(sparse_FIR_tilde_class, (t_method)sparse_FIR_tilde_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(sparse_FIR_tilde_class, (t_method)sparse_FIR_tilde_order, gensym("order"), A_FLOAT, 0); + class_addmethod(sparse_FIR_tilde_class, (t_method)sparse_FIR_tilde_order, gensym("size"), A_FLOAT, 0); +} |