aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/mtx_mul~.c946
-rw-r--r--src/mtx_tilde.c413
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();
-}