/* * iemmatrix * * objects for manipulating simple matrices * mostly refering to matlab/octave matrix functions * * Copyright (c) 2005, Franz Zotter * IEM, Graz, Austria * * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. * */ #include "iemmatrix.h" static t_class *mtx_decay_class; static t_symbol *row_sym; static t_symbol *col_sym; static t_symbol *col_sym2; typedef struct _MTXDecay_ MTXDecay; struct _MTXDecay_ { t_object x_obj; int rows; int columns; int size; int decay_direction; t_symbol *decay_mode; t_float decay_parameter; t_outlet *list_outlet; t_atom *list_out; t_atom *list_in; t_float *x; t_float *y; }; static void deleteMTXDecay (MTXDecay *mtx_decay_obj) { if (mtx_decay_obj->list_out) freebytes (mtx_decay_obj->list_out, sizeof(t_atom)*(mtx_decay_obj->size+2)); if (mtx_decay_obj->x) freebytes (mtx_decay_obj->x, sizeof(t_float)*(mtx_decay_obj->size)); if (mtx_decay_obj->y) freebytes (mtx_decay_obj->y, sizeof(t_float)*(mtx_decay_obj->size)); } static void mTXSetDecayParameter (MTXDecay *mtx_decay_obj, t_float d_param) { d_param = (d_param > 0.0f)?d_param:0.0f; d_param = (d_param < 1.0f)?d_param:1.0f; mtx_decay_obj->decay_parameter = d_param; } static void mTXSetDecayDirection (MTXDecay *mtx_decay_obj, t_float c_dir) { int direction = (int) c_dir; mtx_decay_obj->decay_direction = (direction==-1)?direction:1; } static void mTXSetDecayMode (MTXDecay *mtx_decay_obj, t_symbol *c_mode) { mtx_decay_obj->decay_mode = c_mode; } static void *newMTXDecay (t_symbol *s, int argc, t_atom *argv) { MTXDecay *mtx_decay_obj = (MTXDecay *) pd_new (mtx_decay_class); int sym_count=0; int first_sym=argc; int n=0; mTXSetDecayMode (mtx_decay_obj, gensym(":")); mTXSetDecayDirection (mtx_decay_obj, 1); mTXSetDecayParameter (mtx_decay_obj, .9f); argc = ((argc<3)?argc:3); while (n < argc) { if (argv[n].a_type == A_SYMBOL) { sym_count++; first_sym = (first_sym= 1) mTXSetDecayMode (mtx_decay_obj, atom_getsymbol(argv+first_sym)); if (sym_count > 1) { post("mtx_decay: args after pos %d ignored. supposed to be non-symbolic",first_sym); argc = first_sym+1; } switch (argc) { case 3: if (first_sym < 2) mTXSetDecayDirection (mtx_decay_obj, atom_getfloat (argv+2)); case 2: if (first_sym < 1) mTXSetDecayParameter (mtx_decay_obj, atom_getfloat (argv+1)); else if (first_sym > 1) mTXSetDecayDirection (mtx_decay_obj, atom_getfloat(argv+1)); case 1: if (first_sym != 0) mTXSetDecayParameter (mtx_decay_obj, atom_getfloat (argv)); } mtx_decay_obj->list_outlet = outlet_new (&mtx_decay_obj->x_obj, gensym("matrix")); return ((void *) mtx_decay_obj); } static void mTXDecayBang (MTXDecay *mtx_decay_obj) { if (mtx_decay_obj->list_out) outlet_anything(mtx_decay_obj->list_outlet, gensym("matrix"), mtx_decay_obj->size+2, mtx_decay_obj->list_out); } static void writeFloatIntoList (int n, t_atom *l, t_float *f) { for (;n--;f++, l++) SETFLOAT (l, *f); } static void readFloatFromList (int n, t_atom *l, t_float *f) { while (n--) *f++ = atom_getfloat (l++); } static void readFloatFromListModulo (int n, int m, t_atom *l, t_float *f) { t_atom *ptr = l; int count1, count2; n /= m; count1 = m; while (count1--) for (count2 = n, ptr = l++; count2--; ptr += m, f++) *f = atom_getfloat (ptr); } static void writeFloatIntoListModulo (int n, int m, t_atom *l, t_float *f) { t_atom *ptr = l; int count1, count2; n /= m; count1 = m; while (count1--) for (count2 = n, ptr = l++; count2--; ptr += m, f++) SETFLOAT(ptr,*f); } static void deCay (int n, t_float *x, t_float *y, t_float alpha) { t_float decay = *x; t_float oneminusalpha = 1.0f-alpha; for (;n--; x++, y++) { decay = alpha * decay + oneminusalpha * *x; *y = decay = (decay < *x)? *x : decay; } } static void deCayReverse (int n, t_float *x, t_float *y, t_float alpha) { t_float decay = *x; t_float oneminusalpha = 1.0f-alpha; for (;n--; x--, y--) { decay = alpha * decay + oneminusalpha * *x; *y = decay = (decay < *x)? *x : decay; } } static void mTXDecayMatrix (MTXDecay *mtx_decay_obj, t_symbol *s, int argc, t_atom *argv) { int rows = atom_getint (argv++); int columns = atom_getint (argv++); int size = rows * columns; int list_size = argc - 2; t_atom *list_ptr = argv; t_atom *list_out = mtx_decay_obj->list_out; t_float *x = mtx_decay_obj->x; t_float *y = mtx_decay_obj->y; int count; // size check if (!size) { post("mtx_decay: invalid dimensions"); return; } else if (list_sizesize) { x = (t_float *) resizebytes (x, sizeof (t_float) * (mtx_decay_obj->size), sizeof (t_float) * (size)); y = (t_float *) resizebytes (y, sizeof (t_float) * (mtx_decay_obj->size), sizeof (t_float) * (size)); list_out = (t_atom *) resizebytes (list_out, sizeof (t_atom) * (mtx_decay_obj->size+2), sizeof (t_atom) * (size + 2)); } mtx_decay_obj->size = size; mtx_decay_obj->rows = rows; mtx_decay_obj->columns = columns; mtx_decay_obj->list_out = list_out; mtx_decay_obj->x = x; mtx_decay_obj->y = y; // main part // reading matrix from inlet if ((mtx_decay_obj->decay_mode == col_sym) || (mtx_decay_obj->decay_mode == col_sym2)) { readFloatFromListModulo (size, columns, list_ptr, x); columns = mtx_decay_obj->rows; rows = mtx_decay_obj->columns; } else readFloatFromList (size, list_ptr, x); // calculating decay if (mtx_decay_obj->decay_direction == -1) { if ((mtx_decay_obj->decay_mode == col_sym) || (mtx_decay_obj->decay_mode == col_sym2) || (mtx_decay_obj->decay_mode == row_sym)) { x += columns-1; y += columns-1; for (count = rows; count--; x += columns, y += columns) deCayReverse (columns,x,y,mtx_decay_obj->decay_parameter); } else { x += size-1; y += size-1; deCayReverse (size,x,y,mtx_decay_obj->decay_parameter); } } else { if ((mtx_decay_obj->decay_mode == col_sym) || (mtx_decay_obj->decay_mode == col_sym2) || (mtx_decay_obj->decay_mode == row_sym)) for (count = rows; count--; x += columns, y += columns) deCay (columns,x,y,mtx_decay_obj->decay_parameter); else deCay (size,x,y,mtx_decay_obj->decay_parameter); } x = mtx_decay_obj->x; y = mtx_decay_obj->y; // writing matrix to outlet if ((mtx_decay_obj->decay_mode == col_sym) || (mtx_decay_obj->decay_mode == col_sym2)) { columns = mtx_decay_obj->columns; rows = mtx_decay_obj->rows; writeFloatIntoListModulo (size, columns, list_out+2, y); } else writeFloatIntoList (size, list_out+2, y); SETSYMBOL(list_out, gensym("matrix")); SETFLOAT(list_out, rows); SETFLOAT(&list_out[1], columns); outlet_anything(mtx_decay_obj->list_outlet, gensym("matrix"), mtx_decay_obj->size+2, list_out); } void mtx_decay_setup (void) { mtx_decay_class = class_new (gensym("mtx_decay"), (t_newmethod) newMTXDecay, (t_method) deleteMTXDecay, sizeof (MTXDecay), CLASS_DEFAULT, A_GIMME, 0); class_addbang (mtx_decay_class, (t_method) mTXDecayBang); class_addmethod (mtx_decay_class, (t_method) mTXDecayMatrix, gensym("matrix"), A_GIMME,0); class_addmethod (mtx_decay_class, (t_method) mTXSetDecayParameter, gensym("alpha"), A_DEFFLOAT,0); class_addmethod (mtx_decay_class, (t_method) mTXSetDecayMode, gensym("mode"), A_DEFSYMBOL,0); class_addmethod (mtx_decay_class, (t_method) mTXSetDecayDirection, gensym("direction"), A_DEFFLOAT,0); row_sym = gensym("row"); col_sym = gensym("col"); col_sym2 = gensym("column"); } void iemtx_decay_setup(void){ mtx_decay_setup(); }