diff options
author | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-05-09 16:22:29 +0000 |
---|---|---|
committer | IOhannes m zmölnig <zmoelnig@users.sourceforge.net> | 2005-05-09 16:22:29 +0000 |
commit | e1a040030cba3a2272c663af395b9a65c02f4cde (patch) | |
tree | 8b5766ec327bf062f5508ebb881321c01ccf06e3 | |
parent | ba9aeb745c372735ea6034e72e9d96bc60de99e2 (diff) |
moved the content of mtx_tilde.c ([matrix~]) to mtx_mul~.c ([mtx_*~], [matrix_mul_line~], [matrix~])
svn path=/trunk/externals/iem/iemmatrix/; revision=2927
-rw-r--r-- | src/mtx_mul~.c | 946 | ||||
-rw-r--r-- | src/mtx_tilde.c | 413 |
2 files changed, 946 insertions, 413 deletions
diff --git a/src/mtx_mul~.c b/src/mtx_mul~.c new file mode 100644 index 0000000..0dd8928 --- /dev/null +++ b/src/mtx_mul~.c @@ -0,0 +1,946 @@ +/* + * iemmatrix + * + * objects for manipulating simple matrices + * mostly refering to matlab/octave matrix functions + * + * Copyright (c) Thomas Musil, IEM KUG Graz Austria 2000-2003 + * Copyright (c) IOhannes m zmölnig, forum::für::umläute, 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" + + +/* ---------- mtx_*~ - signal matrix multiplication object with message matrix-coeff. ----------- */ + + +/* usage: + * [mtx_*~ <#out> <#in>]: multiply #in signals with a <#out,#in>-matrix to get #out-signals + * [mtx_*~ <#io>]: multiply #io signals with a <#io,#io>-matrix to get #io-signals + * + * 1st inlet: (message only): the matrix to multiply with (defaults to zero(#out, #in) + * 2nd-(n-1)th inlet: the input signals + * last inlet: the interpolation time in [ms] + * + * this also implements a compatibility layer with old objects from tm and jmz + * that provide basically the same functionality + * + * further note: + * pd does not like signal-objects that don't listen to signals on the very first inlet + * however, the first signal-inlet of [mtx_*~] is the 2nd(!) inlet + * to achieve this, we silently ignore any signal that comes in at the first inlet + */ + +typedef struct matrix_multilde +{ + t_object x_obj; + t_float *x_matcur; + t_float *x_matend; + t_float *x_inc; + t_float *x_biginc; + t_float **x_io; + t_float *x_outsumbuf; + int x_outsumbufsize; + int x_n_in; /* columns */ + int x_n_out; /* rows */ + t_float x_msi; /* for sending floats to signal~ins */ + int x_retarget; + t_float x_time_ms; + int x_remaining_ticks; + t_float x_ms2tick; + t_float x_1overn; + int x_compat; /* 0=mtx_*~; 1=matrix_mul_line~; 2=matrix~ */ +} t_matrix_multilde; + +t_class *matrix_multilde_class; + +static void matrix_multilde_time(t_matrix_multilde *x, t_floatarg time_ms) +{ + if(time_ms <= 0.0f) + time_ms = 0.0f; + x->x_time_ms = time_ms; +} + +static void matrix_multilde_matrix_set(t_matrix_multilde *x, int argc, t_atom *argv, int transpose) +{ + int col, row, i, length; + t_float *matcur = x->x_matcur; + t_float *matend = x->x_matend; + + if(argc<2) + { + post("mtx_*~ : bad matrix: <int> out_rows <int> in_cols !"); + return; + } + + row = atom_getint(argv); + argv++; + col = atom_getint(argv); + argv++; + argc-=2; + + if(transpose){ + int dummy=row; + row=col; + col=dummy; + } + + if((col!=x->x_n_in)||(row!=x->x_n_out)) + { + post("mtx_*~ : matrix dimensions do not match (%dx%d != %dx%d)!!", col, row, x->x_n_in, x->x_n_out); + return; + } + if(argc<row*col) + { + post("mtx_*~ : reduced matrices not yet supported"); + return; + } + + length = col * row; + + if(transpose){ + // we need to transpose the matrix + for(i=0; i<row; i++){ + int j=0; + for(j=0; j<col; j++){ + *matend++=atom_getfloat(argv+i+j*row); + } + } + } else + for(i=0; i<length; i++) + *matend++=atom_getfloat(argv++); + + if(x->x_time_ms <= 0.0f){ + matend = x->x_matend; + for(i=0; i<length; i++) + *matcur++=*matend++; + x->x_remaining_ticks = x->x_retarget = 0; + } else x->x_retarget = 1; +} +static void matrix_multilde_matrix(t_matrix_multilde *x, t_symbol *s, int argc, t_atom *argv){ + matrix_multilde_matrix_set(x,argc, argv, 0); +} +static void matrix_multilde_matrixT(t_matrix_multilde *x, t_symbol *s, int argc, t_atom *argv){ + // transpose the matrix before setting it + matrix_multilde_matrix_set(x,argc, argv, 1); +} +static void matrix_multilde_element(t_matrix_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, row, n_in_cols=x->x_n_in; + t_float element; + t_float *matcur = x->x_matcur; + t_float *matend = x->x_matend; + + if(argc != 3) + { + post("mtx_*~ : bad element: 3 floats: <int> out_row <int> in_col <float> element !"); + return; + } + + row = atom_getint(argv) - 1; + col = atom_getint(argv+1) - 1; + element = atom_getfloat(argv+2); + + if((row >= x->x_n_out) || (row < 0)) + { + post("mtx_*~ : row dimensions do not match !!"); + return; + } + if((col >= n_in_cols) || (col < 0)) + { + post("mtx_*~ : col dimensions do not match !!"); + return; + } + + matend += row * n_in_cols + col; + matcur += row * n_in_cols + col; + + if(x->x_time_ms <= 0.0f) + { + *matend = *matcur = element; + x->x_remaining_ticks = x->x_retarget = 0; + } + else + { + *matend = element; + x->x_retarget = 1; + } +} + +static void matrix_multilde_row(t_matrix_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int col, nth_row, i; + t_float *matcur = x->x_matcur; + t_float *matend = x->x_matend; + + if(argc<1) + { + post("mtx_*~ : bad row: <int> in_row !"); + return; + } + + nth_row = atom_getint(argv) - 1; + argv++; + argc--; + + if((nth_row >= x->x_n_out) || (nth_row < 0)) + { + post("mtx_*~ : row dimensions do not match !!"); + return; + } + col = x->x_n_in; + if(argc < col) + { + post("mtx_*~ : col dimensions do not match !!"); + return; + } + + matend += nth_row * col; + matcur += nth_row * col; + if(x->x_time_ms <= 0.0f) + { + for(i=0; i<col; i++) + { + *matend++ = *matcur++ = atom_getfloat(argv); + argv++; + } + x->x_remaining_ticks = x->x_retarget = 0; + } + else + { + for(i=0; i<col; i++) + { + *matend++ = atom_getfloat(argv); + argv++; + } + x->x_retarget = 1; + } +} + +static void matrix_multilde_col(t_matrix_multilde *x, t_symbol *s, int argc, t_atom *argv) +{ + int row, col, nth_col, i; + t_float *matcur = x->x_matcur; + t_float *matend = x->x_matend; + + if(argc<1) + { + post("mtx_*~ : bad col: <int> in_cols !"); + return; + } + + nth_col = atom_getint(argv) - 1; + argv++; + argc--; + + col = x->x_n_in; + if((nth_col < 0)||(nth_col >= col)) + { + post("mtx_*~ : col dimensions do not match !!"); + return; + } + row = x->x_n_out; + if(argc < row) + { + post("mtx_*~ : row dimensions do not match !!"); + return; + } + + matend += nth_col; + matcur += nth_col; + if(x->x_time_ms <= 0.0f) + { + for(i=0; i<row; i++) + { + *matend = *matcur = atom_getfloat(argv); + argv++; + matend += col; + matcur += col; + } + x->x_remaining_ticks = x->x_retarget = 0; + } + else + { + for(i=0; i<row; i++) + { + *matend = atom_getfloat(argv); + argv++; + matend += col; + matcur += col; + } + x->x_retarget = 1; + } +} + +static void matrix_multilde_stop(t_matrix_multilde *x) +{ + int i = x->x_n_out*x->x_n_in; + t_float *matend=x->x_matend; + t_float *matcur=x->x_matcur; + + while(i--) + { + *matend++ = *matcur++; + } + x->x_remaining_ticks = x->x_retarget = 0; +} + +/* the dsp thing */ + +static t_int *matrix_multilde_perf8(t_int *w) +{ + t_matrix_multilde *x = (t_matrix_multilde *)(w[1]); + int n = (int)(w[2]); + t_float **io = x->x_io; + t_float *outsum, *houtsum; + t_float *matcur, *matend; + t_float *inc1 ,*biginc, inc; + int n_in = x->x_n_in; /* columns */ + int n_out = x->x_n_out; /* rows */ + t_float *in, *out, mul, bigmul; + int r, c, i; + + if(x->x_retarget) + { + int nticks = (int)(x->x_time_ms * x->x_ms2tick); + + if(!nticks) + nticks = 1; + x->x_remaining_ticks = nticks; + inc1 = x->x_inc; + biginc = x->x_biginc; + matcur = x->x_matcur; + matend = x->x_matend; + mul = x->x_1overn / (float)nticks; + bigmul = 1.0f / (float)nticks; + i = n_out*n_in; + while(i--) + { + inc = *matend++ - *matcur++; + *inc1++ = inc * mul; + *biginc++ = inc * bigmul; + } + x->x_retarget = 0; + //post("time = %f ms, ticks = %d, inc = %f", x->x_time_ms, nticks, *inc); + } + + if(x->x_remaining_ticks) + { + inc1 = x->x_inc; + biginc = x->x_biginc; + matcur = x->x_matcur; + /* 1. output-vector-row */ + in = io[0]; + houtsum = x->x_outsumbuf; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = in[0] * mul; + mul += inc; + outsum[1] = in[1] * mul; + mul += inc; + outsum[2] = in[2] * mul; + mul += inc; + outsum[3] = in[3] * mul; + mul += inc; + outsum[4] = in[4] * mul; + mul += inc; + outsum[5] = in[5] * mul; + mul += inc; + outsum[6] = in[6] * mul; + mul += inc; + outsum[7] = in[7] * mul; + mul += inc; + } + *matcur++ += *biginc++; + for(c=1; c<n_in; c++)/* c+1. element of 1. row */ + { + in = io[c]; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] += in[0] * mul; + mul += inc; + outsum[1] += in[1] * mul; + mul += inc; + outsum[2] += in[2] * mul; + mul += inc; + outsum[3] += in[3] * mul; + mul += inc; + outsum[4] += in[4] * mul; + mul += inc; + outsum[5] += in[5] * mul; + mul += inc; + outsum[6] += in[6] * mul; + mul += inc; + outsum[7] += in[7] * mul; + mul += inc; + } + *matcur++ += *biginc++; + } + for(r=1; r<n_out; r++)/* 2. .. n_out. output-vector-row */ + { + in = io[0]; + houtsum += n; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = in[0] * mul; + mul += inc; + outsum[1] = in[1] * mul; + mul += inc; + outsum[2] = in[2] * mul; + mul += inc; + outsum[3] = in[3] * mul; + mul += inc; + outsum[4] = in[4] * mul; + mul += inc; + outsum[5] = in[5] * mul; + mul += inc; + outsum[6] = in[6] * mul; + mul += inc; + outsum[7] = in[7] * mul; + mul += inc; + } + *matcur++ += *biginc++; + for(c=1; c<n_in; c++)/* c+1. element of r+1. row */ + { + in = io[c]; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] += in[0] * mul; + mul += inc; + outsum[1] += in[1] * mul; + mul += inc; + outsum[2] += in[2] * mul; + mul += inc; + outsum[3] += in[3] * mul; + mul += inc; + outsum[4] += in[4] * mul; + mul += inc; + outsum[5] += in[5] * mul; + mul += inc; + outsum[6] += in[6] * mul; + mul += inc; + outsum[7] += in[7] * mul; + mul += inc; + } + *matcur++ += *biginc++; + } + } + + if(!--x->x_remaining_ticks) + { + matcur = x->x_matcur; + matend = x->x_matend; + i = n_in * n_out; + while(i--) + *matcur++ = *matend++; + } + } + else + { + matend = x->x_matend; + /* 1. output-vector-row */ + in = io[0]; + houtsum = x->x_outsumbuf; + outsum = houtsum; + mul = *matend++; + if(mul == 0.0f) + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = 0.0f; + outsum[1] = 0.0f; + outsum[2] = 0.0f; + outsum[3] = 0.0f; + outsum[4] = 0.0f; + outsum[5] = 0.0f; + outsum[6] = 0.0f; + outsum[7] = 0.0f; + } + } + else + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = in[0] * mul; + outsum[1] = in[1] * mul; + outsum[2] = in[2] * mul; + outsum[3] = in[3] * mul; + outsum[4] = in[4] * mul; + outsum[5] = in[5] * mul; + outsum[6] = in[6] * mul; + outsum[7] = in[7] * mul; + } + } + for(c=1; c<n_in; c++)/* c+1. element of 1. row */ + { + in = io[c]; + outsum = houtsum; + mul = *matend++; + if(mul != 0.0f) + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] += in[0] * mul; + outsum[1] += in[1] * mul; + outsum[2] += in[2] * mul; + outsum[3] += in[3] * mul; + outsum[4] += in[4] * mul; + outsum[5] += in[5] * mul; + outsum[6] += in[6] * mul; + outsum[7] += in[7] * mul; + } + } + } + for(r=1; r<n_out; r++)/* 2. .. n_out. output-vector-row */ + { + in = io[0]; + houtsum += n; + outsum = houtsum; + mul = *matend++; + if(mul == 0.0f) + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = 0.0f; + outsum[1] = 0.0f; + outsum[2] = 0.0f; + outsum[3] = 0.0f; + outsum[4] = 0.0f; + outsum[5] = 0.0f; + outsum[6] = 0.0f; + outsum[7] = 0.0f; + } + } + else + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] = in[0] * mul; + outsum[1] = in[1] * mul; + outsum[2] = in[2] * mul; + outsum[3] = in[3] * mul; + outsum[4] = in[4] * mul; + outsum[5] = in[5] * mul; + outsum[6] = in[6] * mul; + outsum[7] = in[7] * mul; + } + } + for(c=1; c<n_in; c++)/* c+1. element of r+1. row */ + { + in = io[c]; + outsum = houtsum; + mul = *matend++; + if(mul != 0.0f) + { + for(i=n; i; i -= 8, outsum += 8, in += 8) + { + outsum[0] += in[0] * mul; + outsum[1] += in[1] * mul; + outsum[2] += in[2] * mul; + outsum[3] += in[3] * mul; + outsum[4] += in[4] * mul; + outsum[5] += in[5] * mul; + outsum[6] += in[6] * mul; + outsum[7] += in[7] * mul; + } + } + } + } + } + outsum = x->x_outsumbuf; + for(r=0; r<n_out; r++)/* output-vector-row */ + { + out = io[n_in+r]; + for (i=n; i; i -= 8, out += 8, outsum += 8) + { + out[0] = outsum[0]; + out[1] = outsum[1]; + out[2] = outsum[2]; + out[3] = outsum[3]; + out[4] = outsum[4]; + out[5] = outsum[5]; + out[6] = outsum[6]; + out[7] = outsum[7]; + } + } + return (w+3); +} +static t_int *matrix_multilde_perform(t_int *w) +{ + t_matrix_multilde *x = (t_matrix_multilde *)(w[1]); + int n = (int)(w[2]); + t_float **io = x->x_io; + t_float *outsum, *houtsum; + t_float *matcur, *matend; + t_float *inc1 ,*biginc, inc; + int n_in = x->x_n_in; /* columns */ + int n_out = x->x_n_out; /* rows */ + t_float *in, *out, mul, bigmul; + int r, c, i; + + if(x->x_retarget) + { + int nticks = (int)(x->x_time_ms * x->x_ms2tick); + + if(!nticks) + nticks = 1; + x->x_remaining_ticks = nticks; + inc1 = x->x_inc; + biginc = x->x_biginc; + matcur = x->x_matcur; + matend = x->x_matend; + mul = x->x_1overn / (float)nticks; + bigmul = 1.0f / (float)nticks; + i = n_out*n_in; + while(i--) + { + inc = *matend++ - *matcur++; + *inc1++ = inc * mul; + *biginc++ = inc * bigmul; + } + x->x_retarget = 0; + } + + if(x->x_remaining_ticks) + { + inc1 = x->x_inc; + biginc = x->x_biginc; + matcur = x->x_matcur; + /* 1. output-vector-row */ + in = io[0]; + houtsum = x->x_outsumbuf; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + i=n; + while(i--) + { + *outsum++ = *in++ * mul; + mul += inc; + } + *matcur++ += *biginc++; + for(c=1; c<n_in; c++)/* c+1. element of 1. row */ + { + in = io[c]; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + i=n; + while(i--) + { + *outsum++ += *in++ * mul; + mul += inc; + } + *matcur++ += *biginc++; + } + for(r=1; r<n_out; r++)/* 2. .. n_out. output-vector-row */ + { + in = io[0]; + houtsum += n; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + i=n; + while(i--) + { + *outsum++ = *in++ * mul; + mul += inc; + } + *matcur++ += *biginc++; + for(c=1; c<n_in; c++)/* c+1. element of r+1. row */ + { + in = io[c]; + outsum = houtsum; + inc = *inc1++; + mul = *matcur; + i=n; + while(i--) + { + *outsum++ += *in++ * mul; + mul += inc; + } + *matcur++ += *biginc++; + } + } + + if(!--x->x_remaining_ticks) + { + matcur = x->x_matcur; + matend = x->x_matend; + i = n_in * n_out; + while(i--) + *matcur++ = *matend++; + } + } + else + { + matend = x->x_matend; + /* 1. output-vector-row */ + in = io[0]; + houtsum = x->x_outsumbuf; + outsum = houtsum; + mul = *matend++; + i=n; + if(mul == 0.0f) + while(i--)*outsum++ = 0.0f; + else + while(i--)*outsum++ = *in++ * mul; + + for(c=1; c<n_in; c++)/* c+1. element of 1. row */ + { + in = io[c]; + outsum = houtsum; + mul = *matend++; + if(mul != 0.0f) + { + i=n; + while(i--) *outsum++ += *in++ * mul; + } + } + for(r=1; r<n_out; r++)/* 2. .. n_out. output-vector-row */ + { + in = io[0]; + houtsum += n; + outsum = houtsum; + mul = *matend++; + i=n; + if(mul == 0.0f) + while(i--)*outsum++ = 0.0f; + else + while(i--)*outsum++ = *in++ * mul; + + for(c=1; c<n_in; c++)/* c+1. element of r+1. row */ + { + in = io[c]; + outsum = houtsum; + mul = *matend++; + i=n; + if(mul != 0.0f) + while(i--)*outsum++ += *in++ * mul; + } + } + } + outsum = x->x_outsumbuf; + + for(r=0; r<n_out; r++)/* output-vector-row */ + { + out = io[n_in+r]; + i=n; + while(i--)*out++ = *outsum++; + } + + return (w+3); +} +static void matrix_multilde_dsp(t_matrix_multilde *x, t_signal **sp) +{ + int i, n=sp[0]->s_n * x->x_n_out; + /* [mtx_*~] ignores the signal on the very 1st inlet */ + int compat_offset=(x->x_compat)?0:1; + + if(!x->x_outsumbuf) + { + x->x_outsumbufsize = n; + x->x_outsumbuf = (t_float *)getbytes(x->x_outsumbufsize * sizeof(t_float)); + } + else if(x->x_outsumbufsize != n) + { + x->x_outsumbuf = (t_float *)resizebytes(x->x_outsumbuf, + x->x_outsumbufsize*sizeof(t_float), + n*sizeof(t_float)); + x->x_outsumbufsize = n; + } + + n = x->x_n_in + x->x_n_out; + for(i=0; i<n; i++) + x->x_io[i] = sp[i+compat_offset]->s_vec; + + n = sp[0]->s_n; + x->x_ms2tick = 0.001f * (float)(sp[0]->s_sr) / (float)n; + x->x_1overn = 1.0f / (float)n; + + + if(n&7) + { + post("adding perform"); + dsp_add(matrix_multilde_perform, 2, x, n); + } + else { + post("adding perf8"); + dsp_add(matrix_multilde_perf8, 2, x, n); + } +} + + +/* setup/setdown things */ + +static void matrix_multilde_free(t_matrix_multilde *x) +{ + freebytes(x->x_matcur, x->x_n_in * x->x_n_out * sizeof(t_float)); + freebytes(x->x_matend, x->x_n_in * x->x_n_out * sizeof(t_float)); + freebytes(x->x_inc, x->x_n_in * x->x_n_out * sizeof(t_float)); + freebytes(x->x_biginc, x->x_n_in * x->x_n_out * sizeof(t_float)); + freebytes(x->x_io, (x->x_n_in + x->x_n_out) * sizeof(t_float *)); + if(x->x_outsumbuf) + freebytes(x->x_outsumbuf, x->x_outsumbufsize * sizeof(t_float)); +} + +static void *matrix_multilde_new(t_symbol *s, int argc, t_atom *argv) +{ + t_matrix_multilde *x = (t_matrix_multilde *)pd_new(matrix_multilde_class); + int i, n; + + + /* arguments parsing: + * this might depend on whether we are creating an object + * [mtx_*~], [matrix~] or [matrix_mul_line~] + * + * [mtx_*~ [#out [#in [time]]]]: in1=matrix; in2-in(#in+1)=signals; in(#in+2)=time + * [matrix~ [#in [#out [time]]]]: in1-in(#in)=signals; in(#in+1)=matrix; in(#in+2)=time + * [matrix_mul_line~ [#in [#out [time]]]]: in1=matrix; in1=time; in1-in(#in):=signals + * + * furthermore: + * [mtx_*~] and [matrix_mul_line~] : O^=A*I^ + * [matrix~] : O^'=I^'*B + * + * with "matrix=(A or B)" and "A=B'" + */ + + t_atom*ap_in =argv+1; + t_atom*ap_out =argv+0; + t_atom*ap_time=argv+2; + + x->x_compat=0; + + if(s==gensym("matrix~")){ + error("[matrix~] is deprecated! use [mtx_*~] instead!!"); + x->x_compat=2; + } + else if (s==gensym("matrix_mul_line~")){ + error("[matrix_mul_line~] is deprecated! use [mtx_*~] instead!!"); + x->x_compat=1; + } + + if(x->x_compat){ + ap_in=argv+0; + ap_out=argv+1; + } + + switch(argc) + { + case 0: + x->x_n_in = x->x_n_out = 1; + x->x_time_ms = (x->x_compat==2)?0.f:50.0f; + break; + case 1: + x->x_n_in = x->x_n_out = (int)atom_getint(argv); + x->x_time_ms = (x->x_compat==2)?0.f:50.0f; + break; + case 2: + x->x_n_in = (int)atom_getint(ap_in); + x->x_n_out = (int)atom_getint(ap_out); + x->x_time_ms = (x->x_compat==2)?0.f:50.0f; + break; + default: + x->x_n_in = (int)atom_getint(ap_in); + x->x_n_out = (int)atom_getint(ap_out); + x->x_time_ms = atom_getfloat(ap_time); + break; + } + + + /* sanity check */ + if(x->x_time_ms < 0.0f) + x->x_time_ms = (x->x_compat==1)?50.f:0.0f; + if(x->x_n_in < 1) + x->x_n_in = 1; + if(x->x_n_out < 1) + x->x_n_out = 1; + + /* creating signal ins & outs */ + i = x->x_n_in; + if(x->x_compat)i--; + while(i--) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + i = x->x_n_out; + while(i--) + outlet_new(&x->x_obj, &s_signal); + + /* creating the matrix-inlet for [matrix~] */ + if(x->x_compat==2) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); + + /* creating time-inlet (not for [matrix_mul_linie~]) */ + if(x->x_compat!=1) + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("time")); + + + /* setting up internal values */ + x->x_msi = 0; + x->x_outsumbuf = (t_float *)0; + x->x_outsumbufsize = 0; + x->x_matcur = (t_float *)getbytes(x->x_n_in * x->x_n_out * sizeof(t_float)); + x->x_matend = (t_float *)getbytes(x->x_n_in * x->x_n_out * sizeof(t_float)); + x->x_inc = (t_float *)getbytes(x->x_n_in * x->x_n_out * sizeof(t_float)); + x->x_biginc = (t_float *)getbytes(x->x_n_in * x->x_n_out * sizeof(t_float)); + x->x_io = (t_float **)getbytes((x->x_n_in + x->x_n_out) * sizeof(t_float *)); + x->x_remaining_ticks = 0; + x->x_retarget = 0; + x->x_ms2tick = 0.001f * 44100.0f / 64.0f; /* will be set in the dsp-routine */ + x->x_1overn = 1.0f / 64.0f; /* will be set in the dsp-routine */ + + /* setting up internal matrices */ + n = x->x_n_in * x->x_n_out; + for(i=0; i<n; i++) + { + x->x_matcur[i] = 0.0f; + x->x_matend[i] = 0.0f; + x->x_inc[i] = 0.0f; + x->x_biginc[i] = 0.0f; + } + return (x); +} + +void mtx_mul_tilde_setup(void) +{ + matrix_multilde_class = class_new(gensym("mtx_*~"), + (t_newmethod)matrix_multilde_new, + (t_method)matrix_multilde_free, + sizeof(t_matrix_multilde), 0, A_GIMME, 0); + + class_addcreator((t_newmethod)matrix_multilde_new, gensym("matrix_mul~"), A_GIMME, 0); + /* compatibility with tm's iem_matrix */ + class_addcreator((t_newmethod)matrix_multilde_new, gensym("matrix_mul_line~"), A_GIMME, 0); + /* compatibility with jmz's zexy */ + class_addcreator((t_newmethod)matrix_multilde_new, gensym("matrix~"), A_GIMME, 0); + + + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_dsp, gensym("dsp"), 0); + CLASS_MAINSIGNALIN(matrix_multilde_class, t_matrix_multilde, x_msi); + + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_matrix, gensym("matrix"), A_GIMME, 0); + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_element, gensym("element"), A_GIMME, 0); + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_row, gensym("row"), A_GIMME, 0); + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_col, gensym("col"), A_GIMME, 0); + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_stop, gensym("stop"), 0); + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_time, gensym("time"), A_FLOAT, 0); + + class_addmethod(matrix_multilde_class, (t_method)matrix_multilde_matrixT, gensym(""), A_GIMME, 0); + + class_sethelpsymbol(matrix_multilde_class, gensym("iemmatrix/matrix_mul~")); +} diff --git a/src/mtx_tilde.c b/src/mtx_tilde.c deleted file mode 100644 index ec6ed05..0000000 --- a/src/mtx_tilde.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * iemmatrix - * - * objects for manipulating simple matrices - * mostly refering to matlab/octave matrix functions - * - * Copyright (c) IOhannes m zmölnig, forum::für::umläute - * 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" - - -/* - the sigmatrix objects :: - mtx_*~ : multiply a n-vector of in~ with a matrix to get a m-vector of out~ - line~ between the 2 matrices, to make it useable as a mixer -*/ - - -/* --------------------------- matrix~ ---------------------------------- - * - * multiply a n-vector of signals with a (n*m) matrix, to get m output-streams. - * make the (n*m)-matrix of scalars to be liny~ - * - * 1703:forum::für::umläute:2001 - */ - -static t_class *mtx_multilde_class; - -typedef struct _mtx_multilde { - t_object x_obj; - - t_float time; - int ticksleft; - int retarget; - t_float msec2tick; - - t_float**value; - t_float**target; - t_float**increment; /* single precision is really a bad, especially when doing long line~s. - * but the biginc (like in msp's line~ (d_ctl.c) is far too expensive... */ - t_float**sigIN; - t_float**sigOUT; - t_float *sigBUF; - - int n_sigIN; /* columns */ - int n_sigOUT; /* rows */ - - int compatibility; /* 0=default; 1=zexy; 2=iemlib */ -} t_mtx_multilde; - -/* the message thing */ - -static void mtx_multilde_matrix_default(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) -{ - int col, row, c=0, r=0; - - if (argc<2){ - post("matrix~ : bad matrix !"); - return; - } - - row = atom_getfloat(argv++); - col = atom_getfloat(argv++); - argc-=2; - - if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ - post("matrix~ : matrix dimensions do not match !!"); - return; - } - if(argc<row*col){ - post("matrix~ : reduced matrices not yet supported"); - return; - } - - if (x->time<=0) { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); - x->time=x->ticksleft=x->retarget=0; - } else { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=atom_getfloat(argv++); - x->retarget=1; - } -} - -static void mtx_multilde_matrix_zexy(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) -{ - int col, row, c=0, r=0; - - if (argc<2){ - post("matrix~ : bad matrix !"); - return; - } - - row = atom_getfloat(argv++); - col = atom_getfloat(argv++); - argc-=2; - - if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ - post("matrix~ : matrix dimensions do not match !!"); - return; - } - if(argc<row*col){ - post("matrix~ : reduced matrices not yet supported"); - return; - } - - if (x->time<=0) { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); - x->time=x->ticksleft=x->retarget=0; - } else { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=atom_getfloat(argv++); - x->retarget=1; - } -} - -static void mtx_multilde_matrix_iemlib(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv) -{ - int col, row, c=0, r=0; - - if (argc<2){ - post("matrix~ : bad matrix !"); - return; - } - - row = atom_getfloat(argv++); - col = atom_getfloat(argv++); - argc-=2; - - if((col!=x->n_sigOUT)||(row!=x->n_sigIN)){ - post("matrix~ : matrix dimensions do not match !!"); - return; - } - if(argc<row*col){ - post("matrix~ : reduced matrices not yet supported"); - return; - } - - if (x->time<=0) { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=x->value[c][r]=atom_getfloat(argv++); - x->time=x->ticksleft=x->retarget=0; - } else { - for(r=0; r<row; r++) - for(c=0; c<col; c++) - x->target[c][r]=atom_getfloat(argv++); - x->retarget=1; - } -} -static void mtx_multilde_matrix(t_mtx_multilde *x, t_symbol *s, int argc, t_atom *argv){ - switch (x->compatibility){ - default:mtx_multilde_matrix_default(x,s,argc,argv); - break; - case 1:mtx_multilde_matrix_zexy(x,s,argc,argv); - break; - case 2:mtx_multilde_matrix_iemlib(x,s,argc,argv); - break; - } -} - -static void mtx_multilde_stop(t_mtx_multilde *x) -{ - int c = x->n_sigOUT, r; - t_float *tgt, *val; - while(c--){ - tgt=x->target[c]; - val=x->value [c]; - r=x->n_sigIN; - while(r--)*tgt++=*val++; - } - x->ticksleft = x->retarget = 0; -} - - -/* the dsp thing */ - -static t_int *mtx_multilde_perform(t_int *w) -{ - t_mtx_multilde *x = (t_mtx_multilde *)(w[1]); - int n = (int)(w[2]); - - int r, c; - - t_float **out = x->sigOUT; - t_float **in = x->sigIN; - - t_float *buf = x->sigBUF, *sigBUF = buf; - - t_float **value = x->value; - t_float **target = x->target; - t_float **increment = x->increment; - - t_float *inc, *val, *tgt; - - int n_IN=x->n_sigIN, n_OUT=x->n_sigOUT; - - if (x->retarget) { - int nticks = x->time * x->msec2tick; - t_float oneovernos; - - if (!nticks) nticks = 1; - oneovernos = 1./(nticks*n); - x->ticksleft = nticks; - - c = n_OUT; - while(c--) { - inc=increment[c]; - val=value[c]; - tgt=target[c]; - r=n_IN; - while(r--)*inc++=(*tgt++-*val++)*oneovernos; - } - - x->retarget = 0; - } - - if (x->ticksleft) { - int N=n-1; - n=-1; - // while (n--) { - while(n++<N){ - c = n_OUT; - while(c--) { - t_float sum = 0; - val = value[c]+n_IN-1; - inc = increment[c]+n_IN-1; - r=n_IN; - - while(r--)sum+=in[r][n]*(*val--+=*inc--); - - sigBUF[c]=sum; - } - buf = sigBUF; - c = n_OUT; - while(c--)out[c][n]=*buf++; - } - if (!--x->ticksleft) { - c = n_OUT; - while(c--){ - val=value[c]; - tgt=target[c]; - r=n_IN; - while(r--)*val++=*tgt++; - } - } - } else { /* no ticks left */ - while (n--) { - c = n_OUT; - while(c--) { - t_float sum = 0; - val = value[c]+n_IN-1; - r = n_IN; - while(r--)sum+=in[r][n]**val--; - sigBUF[c]=sum; - } - buf = sigBUF; - c = n_OUT; - while(c--)out[c][n]=*buf++; - } - } - return (w+3); -} - -static void mtx_multilde_dsp(t_mtx_multilde *x, t_signal **sp) -{ - int o = x->n_sigOUT, i=x->n_sigIN, n=0; - t_float **dummy = x->sigIN; - - while(i--)*dummy++=sp[n++]->s_vec; - - dummy =x->sigOUT; - while(o--)dummy[o]=sp[n++]->s_vec; - - x->msec2tick = sp[0]->s_sr / (1000.f * sp[0]->s_n); - dsp_add(mtx_multilde_perform, 2, x, sp[0]->s_n); -} - - -/* setup/setdown things */ - -static void mtx_multilde_free(t_mtx_multilde *x) -{ - int i = x->n_sigOUT; - while(i--) { - freebytes(x->value [i], x->n_sigOUT * sizeof(t_float *)); - freebytes(x->target [i], x->n_sigOUT * sizeof(t_float *)); - freebytes(x->increment[i], x->n_sigOUT * sizeof(t_float *)); - } - - freebytes(x->value, sizeof(x->value)); - freebytes(x->target, sizeof(x->target)); - freebytes(x->increment, sizeof(x->increment)); - - freebytes(x->sigIN, x->n_sigIN * sizeof(t_float *)); - freebytes(x->sigOUT, x->n_sigOUT * sizeof(t_float *)); - freebytes(x->sigBUF, x->n_sigOUT * sizeof(t_float )); -} - -static void *mtx_multilde_new(t_symbol *s, int argc, t_atom *argv) -{ - t_mtx_multilde *x = (t_mtx_multilde *)pd_new(mtx_multilde_class); - int i; - int InOut=0; - x->compatibility=0; - - if(s==gensym("matrix~")){ // zexy-compat - error("[matrix~] is deprecated");//; use [mtx_*~] instead"); - x->compatibility=1; - InOut=1; - } - - if(s==gensym("matrix_mul~")){ // iemlib-compat - error("[matrix_mul~] is deprecated; use [mtx_*~] instead"); - x->compatibility=2; - InOut=1; - } - - x->time = 0; - - switch (argc) { - case 0: - x->n_sigIN = x->n_sigOUT = 1; - break; - case 1: - x->n_sigIN = x->n_sigOUT = atom_getfloat(argv); - break; - default: - x->time= atom_getfloat(argv+2); - case 2: - if(InOut){ - x->n_sigIN = atom_getfloat(argv); - x->n_sigOUT = atom_getfloat(argv+1); - } else { - x->n_sigOUT = atom_getfloat(argv); - x->n_sigIN = atom_getfloat(argv+1); - } - break; - } - - if (x->time<0) x->time=0; - if (x->n_sigIN <1) x->n_sigIN =1; - if (x->n_sigOUT<1) x->n_sigOUT=1; - - /* the inlets */ - i=x->n_sigIN-1; - while(i--)inlet_new(&x->x_obj,&x->x_obj.ob_pd,&s_signal,&s_signal); - inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("matrix"), gensym("")); - floatinlet_new(&x->x_obj, &x->time); - - /* the outlets */ - i=x->n_sigOUT; - while(i--)outlet_new(&x->x_obj,&s_signal); - - /* make all the buffers */ - x->sigIN = (t_float**)getbytes(x->n_sigIN * sizeof(t_float*)); - x->sigOUT = (t_float**)getbytes(x->n_sigOUT * sizeof(t_float*)); - x->sigBUF = (t_float *)getbytes(x->n_sigOUT * sizeof(t_float )); - - x->value = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); - x->target = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); - x->increment = (t_float **)getbytes(x->n_sigOUT * sizeof(t_float)); - - i = x->n_sigOUT; - while(i--){ - int j = x->n_sigIN; - x->sigOUT [i] = 0; - x->value [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); - x->target [i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); - x->increment[i] = (t_float *)getbytes(x->n_sigIN * sizeof(t_float)); - - while(j--)x->value[i][j]=x->target[i][j]=x->increment[i][j]=0; - } - - i = x->n_sigIN; - while(i--)x->sigIN[i] = 0; - - x->msec2tick = x->ticksleft = x->retarget = 0; - return (x); -} - -static void mtx_multilde_setup(void) -{ - mtx_multilde_class = class_new(gensym("mtx_*~"), (t_newmethod)mtx_multilde_new, - (t_method)mtx_multilde_free, - sizeof(t_mtx_multilde), 0, A_GIMME, 0); - - class_addcreator((t_newmethod)mtx_multilde_new, gensym("matrix~"), A_GIMME,0); - - class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_dsp, gensym("dsp"), 0); - class_addmethod(mtx_multilde_class, nullfn, gensym("signal"), 0); - - class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_matrix, gensym(""), A_GIMME, 0); - class_addmethod(mtx_multilde_class, (t_method)mtx_multilde_stop, gensym("stop"), 0); - - class_sethelpsymbol(mtx_multilde_class, gensym("iemmatrix/matrix~")); -} - -void mtx_tilde_setup(void) -{ - mtx_multilde_setup(); -} |