/*
mtx_preset : store and interpol presets that are in a matrix form
Copyright (C) 2014 Cyrile Henry
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include "m_pd.h"
#include "math.h"
#define sizemaxX 1000
#define sizemaxY 1000
static t_class *mtx_preset_class;
typedef struct _mtx_preset {
t_object x_obj;
t_outlet *main_outlet;
t_int sizeX;
t_int sizeY;
t_float matrix[sizemaxX][sizemaxY+1];
} t_mtx_preset;
t_float mix(t_float X, t_float Y, t_float mix)
{
return (1-mix)*X + mix*Y ;
}
#define min(X, Y) (((X) < (Y)) ? (X) : (Y))
#define max(X, Y) (((X) > (Y)) ? (X) : (Y))
void *mtx_preset_new(t_symbol *s, int argc, t_atom *argv)
{
int i, j;
t_mtx_preset *x = (t_mtx_preset *)pd_new(mtx_preset_class);
x->sizeX = 2;
if ((argc>0) && (argv[0].a_type == A_FLOAT))
x->sizeX = atom_getfloatarg(0, argc, argv);
if (x->sizeX > sizemaxX)
x->sizeX = sizemaxX;
if (x->sizeX < 1)
x->sizeX = 1;
x->sizeY = 2;
if ((argc>1) && (argv[1].a_type == A_FLOAT))
x->sizeY = atom_getfloatarg(1, argc, argv);
if (x->sizeY > sizemaxX)
x->sizeY = sizemaxX;
if (x->sizeY < 1)
x->sizeY = 1;
for (i=0; i < sizemaxX; i++)
for (j=0; j < sizemaxY; j++)
x->matrix[i][j] = 0;
x->main_outlet = outlet_new(&x->x_obj, 0);
return (void *)x;
}
void mtx_preset_resize(t_mtx_preset *x, t_float sizeX, t_float sizeY)
{
x->sizeX = sizeX;
x->sizeY = sizeY;
if (x->sizeX > sizemaxX)
x->sizeX = sizemaxX;
if (x->sizeX < 1)
x->sizeX = 1;
if (x->sizeY > sizemaxX)
x->sizeY = sizemaxX;
if (x->sizeY < 1)
x->sizeY = 1;
}
void mtx_preset_matrix(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
int X,Y, mtxX, mtxY, i, j,k;
if ((argc > 3) && (argv[0].a_type == A_FLOAT) && (argv[1].a_type == A_FLOAT) && (argv[2].a_type == A_FLOAT)) {
// reception de matrix X Y values
// copy data, carfull if matrix and mtx_interpol have different size
mtxX = atom_getfloatarg(0,argc,argv);
mtxY = atom_getfloatarg(1,argc,argv);
X = min(x->sizeX, mtxX);
Y = min(x->sizeY, mtxY);
for (i=0; i < X; i++) {
for (j=0; j < Y; j++) {
k= j*mtxX + i + 2;
if ((argc > k) && (argv[k].a_type == A_FLOAT))
x->matrix[i][j] = atom_getfloatarg(k,argc,argv);
}
}
}
else if ((argc > 0) && (argv[0].a_type == A_FLOAT)) {
// reception de matrix value
for (i=0; i < x->sizeX; i++) {
for (j=0; j < x->sizeY; j++) {
x->matrix[i][j] = atom_getfloatarg(0,argc,argv);
}
}
}
else {
error("bad matrix");
return;
}
}
void mtx_preset_row(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
// reception de row Y values...
int row, i;
if ((argc > 0) && (argv[0].a_type == A_FLOAT))
row = atom_getfloatarg(0,argc,argv);
else {
error("bad row");
return;
}
row = min(x->sizeY-1, row);
row = max(0, row);
for (i=0; i < x->sizeX; i++)
if ((argc > i+1) && (argv[i+1].a_type == A_FLOAT))
x->matrix[i][row] = atom_getfloatarg(i+1,argc,argv);
}
void mtx_preset_col(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
// reception de col X values...
int col, i;
if ((argc > 0) && (argv[0].a_type == A_FLOAT))
col = atom_getfloatarg(0,argc,argv);
else {
error("bad col");
return;
}
col = min(x->sizeX-1, col);
col = max(0, col);
for (i=0; i < x->sizeY; i++)
if ((argc > i+1) && (argv[i+1].a_type == A_FLOAT))
x->matrix[col][i] = atom_getfloatarg(i+1,argc,argv);
}
void mtx_preset_setrow(t_mtx_preset *x, t_float rowtoset, t_float value)
{
// reception de row Y value
int row, i;
row = min(x->sizeY-1, rowtoset);
row = max(0, row);
for (i=0; i < x->sizeX; i++)
x->matrix[i][row] = value;
}
void mtx_preset_setcol(t_mtx_preset *x, t_float coltoset, t_float value)
{
// reception de col X value
int col, i;
col = min(x->sizeX-1, coltoset);
col = max(0, col);
for (i=0; i < x->sizeY; i++)
x->matrix[col][i] = value;
}
void mtx_preset_element(t_mtx_preset *x, t_float posX, t_float posY, t_float value)
{
// reception de element X Y value
if ((posX < x->sizeX) && (posY < x->sizeY) && (posX >= 0) && (posY >= 0)) {
x->matrix[(int)posX][(int)posY] = value;
}
}
void mtx_preset_getMatrix(t_mtx_preset *x)
{
int i, j;
// dump matrix tailleX tailleY datas...
t_atom std_out[x->sizeX*x->sizeY+2];
SETFLOAT(&(std_out[0]),x->sizeX);
SETFLOAT(&(std_out[1]),x->sizeY);
for (i=0; i < x->sizeX; i++)
for (j=0; j < x->sizeY; j++)
SETFLOAT(&(std_out[i+x->sizeX*j+2]),x->matrix[i][j]);
outlet_anything(x->main_outlet, gensym("matrix"),x->sizeX*x->sizeY+2,std_out);
}
void mtx_preset_getRow(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
int i,j, a,b;
t_float c;
t_atom std_out[x->sizeX+1];
if (argc == 0)
for (i=0; i< x->sizeY; i++) {
SETFLOAT(&(std_out[0]),i);
for (j=0; j < x->sizeX; j++) {
SETFLOAT(&(std_out[j+1]),x->matrix[j][i]);
}
outlet_anything(x->main_outlet, gensym("row"),x->sizeX+1,std_out);
}
else if ((argc > 0) && (argv[0].a_type == A_FLOAT)) {
a = floor(atom_getfloatarg(0,argc,argv));
b = a+1;
c = atom_getfloatarg(0,argc,argv)-a;
a = min(a, x->sizeX);
a = max(a,0);
b = min(a, x->sizeX);
b = max(b,0);
for (i=0; i < x->sizeX; i++) {
SETFLOAT(&(std_out[i]),mix(x->matrix[i][a], x->matrix[i][b], c));
}
outlet_list(x->main_outlet, gensym("list"), x->sizeX, std_out);
}
}
void mtx_preset_getElement(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
int i, a, b;
t_float c;
t_atom std_out[2];
if ((argc > 1) && (argv[0].a_type == A_FLOAT) && (argv[1].a_type == A_FLOAT)) {
a = min(atom_getfloatarg(0,argc,argv), x->sizeX);
a = max(a,0);
b = min(atom_getfloatarg(1,argc,argv), x->sizeY);
b = max(b,0);
outlet_float(x->main_outlet, x->matrix[a][b]);
}
else if ((argc > 0) && (argv[0].a_type == A_FLOAT)) {
a = floor(atom_getfloatarg(0,argc,argv));
b = a+1;
c = atom_getfloatarg(0,argc,argv)-floor(atom_getfloatarg(0,argc,argv));
a = min(a, x->sizeX);
a = max(a,0);
b = min(b, x->sizeX);
b = max(b,0);
for (i=0; i < x->sizeX; i++) {
SETFLOAT(&(std_out[0]),i);
SETFLOAT(&(std_out[1]),mix(x->matrix[i][a], x->matrix[i][b], c));
outlet_list(x->main_outlet, gensym("element"), 2, std_out);
}
}
else {
error("bad arguments for getElement");
}
}
void mtx_preset_mixRow(t_mtx_preset *x, t_symbol *s, int argc, t_atom *argv)
{
int i, j;
t_atom std_out[x->sizeX];
t_float row[x->sizeX];
for (i=0; i < x->sizeX; i++)
row[i] = 0;
for (j=0; jsizeY); j++)
for (i=0; i < x->sizeX; i++)
row[i] += x->matrix[i][j] * atom_getfloatarg(j, argc, argv);
for (i=0; i < x->sizeX; i++)
SETFLOAT(&(std_out[i]),row[i]);
outlet_list(x->main_outlet, gensym("list"), x->sizeX, std_out);
}
void mtx_preset_copyRow(t_mtx_preset *x, t_float row1, t_float row2)
{
int i, rowA, rowB;
rowA = min(x->sizeY-1, row1);
rowA = max(0, rowA);
rowB = min(x->sizeY-1, row2);
rowB = max(0, rowB);
for (i=0; i < x->sizeX; i++)
x->matrix[i][rowB] = x->matrix[i][rowA];
}
void mtx_preset_setup(void) {
mtx_preset_class = class_new(gensym("mtx_preset"),
(t_newmethod)mtx_preset_new,
0, sizeof(t_mtx_preset),
CLASS_DEFAULT, A_GIMME, 0);
class_addmethod(mtx_preset_class, (t_method)mtx_preset_matrix, gensym("matrix"),A_GIMME, 0); // put Matrix
// matrix value -> all matrix will be at the float value
// matrix sizeX sizeY values ... -> put the matrix in 0 0
class_addmethod(mtx_preset_class, (t_method)mtx_preset_row, gensym("row"),A_GIMME, 0); // put Row
// row float float ... -> put all value to a row
class_addmethod(mtx_preset_class, (t_method)mtx_preset_col, gensym("col"),A_GIMME, 0); // put Col
// coll float float ... -> put all value to a col
class_addmethod(mtx_preset_class, (t_method)mtx_preset_setrow, gensym("setRow"),A_FLOAT, A_FLOAT, 0); // set Row
// row float float -> put value to a row
class_addmethod(mtx_preset_class, (t_method)mtx_preset_setcol, gensym("setCol"),A_FLOAT, A_FLOAT, 0); // set Col
// coll float float -> put value to a col
class_addmethod(mtx_preset_class, (t_method)mtx_preset_element, gensym("element"),A_FLOAT, A_FLOAT, A_FLOAT, 0); // put 1 element
// element posX posY value
class_addmethod(mtx_preset_class, (t_method)mtx_preset_getMatrix, gensym("getMatrix"), 0); // get matrix (matrix sizeX sizeY value)
class_addmethod(mtx_preset_class, (t_method)mtx_preset_getRow, gensym("getRow"), A_GIMME, 0); // get row
// getRow -> dump all row (row now_number row values)
// getRow row_number -> dump 1 row (values)
// row_number can be float : row will be interpolated
class_addmethod(mtx_preset_class, (t_method)mtx_preset_getElement,gensym("getElement"), A_GIMME, 0); // get element
// get posX posY -> dump 1 element
// get posX -> dump elements from 1 row
// row_number can be float : row will be interpolated
class_addmethod(mtx_preset_class, (t_method)mtx_preset_mixRow, gensym("mixRow"), A_GIMME, 0); // interpol between all row
// mixRow value0 value1 value2 : (value0*row0 + value1*row1 + value2*row2)
class_addmethod(mtx_preset_class, (t_method)mtx_preset_copyRow, gensym("copyRow"), A_FLOAT, A_FLOAT, 0); // copy row 1 to row 2
class_addmethod(mtx_preset_class, (t_method)mtx_preset_resize, gensym("resize"),A_FLOAT, A_FLOAT, 0); // resize matrix
}