WoMax Documentation

# PC/OMax.learn/OMax.learn.c

    00001 /*----------------------------------
    00002  * OMax.learn - OMax.learn.c
    00003  * Created on 13/03/09 by BenCello
    00004  *----------------------------------*/
    00005
    00007
    00009
    00010
    00011 #ifndef __OMAX_LEARN_MAX_API_
    00012 #define __OMAX_LEARN_MAX_API_
    00013
    00014 #include "Oracle_learn.hpp"
    00015
    00016 extern "C"
    00017 {
    00018
    00019 #include "ext.h"                                // standard Max include, always required
    00020 #include "ext_obex.h"                   // required for new style Max object
    00021 #include "jpatcher_api.h"               // required for the color
    00022 #include "jgraphics.h"                  // required for the color
    00023
    00024 #include "OMax.oracle.h"
    00025 #include "OMax.data.h"
    00026
    00031         typedef struct _OMax_learn
    00032         {
    00033                 t_object        ob;
    00034                 t_symbol*       oname;
    00035                 O_DataType      datatype;
    00036                 int                     nbcoeffs;
    00037                 t_symbol*       dataname;
    00038                 bool            obound;
    00039                 O_learner       builder;
    00040                 void*           stateout;
    00041         } t_OMax_learn;
    00042
    00044
    00046         // Prototypes //
    00048
    00049         // Standard Max5 methodes
    00050         void *OMax_learn_new(t_symbol *s, long argc, t_atom *argv);
    00051         void OMax_learn_free(t_OMax_learn *x);
    00052         void OMax_learn_assist(t_OMax_oracle *x, void *b, long io, long index, char *s);
    00053
    00054         // Input/ouput routines
    00055         void OMax_learn_add(t_OMax_learn *x, t_symbol *s, short ac, t_atom * av);
    00056
    00057         // Internal routines
    00058         t_symbol * OMax_learn_dataname(t_symbol * oname);
    00059         bool OMax_learn_bind(t_OMax_learn *x);
    00060
    00061         // Global class pointer variable
    00062         t_class *OMax_learn_class;
    00063
    00065         // Functions //
    00067
    00068         int main(void)
    00069         {
    00070                 t_class *c;
    00071
    00072                 c = class_new("OMax.learn", (method)OMax_learn_new, (method)OMax_learn_free, (long)sizeof(t_OMax_learn),
    00073                                           0L /* leave NULL!! */, A_GIMME, 0);
    00074
    00075                 // assistance
    00076                 class_addmethod(c, (method)OMax_learn_assist,"assist",A_CANT, 0);
    00077
    00078                 // input methods
    00079                 class_addmethod(c, (method)OMax_learn_add, "add", A_GIMME, 0);
    00080
    00081                 class_register(CLASS_BOX, c); /* CLASS_NOBOX */
    00082                 OMax_learn_class = c;
    00083
    00084                 return 0;
    00085         }
    00086
    00088
    00089
    00092         void *OMax_learn_new(t_symbol *s, long argc, t_atom *argv)
    00093         {
    00094                 t_OMax_learn *x = NULL;
    00095
    00096                 if (x = (t_OMax_learn *)object_alloc(OMax_learn_class))
    00097                 {
    00098                         // inlets & outlets
    00099                         x->stateout = intout(x);
    00100
    00102                         x->obound = FALSE;
    00103                         if (argc == 0)
    00104                                 object_error((t_object *)x,"Missing name of the Oracle to build");
    00105                         else
    00106                         {
    00107                                 if (argv->a_type != A_SYM)
    00108                                         object_error((t_object *)x,"First argument must be a symbol (name of an existing Oracle)");
    00109                                 else
    00110                                         x->oname = atom_getsym(argv);
    00111                                 x->dataname = OMax_learn_dataname(x->oname);
    00112                         }
    00113
    00114                         // color
    00115                         t_object *box;
    00116                         t_jrgba colorvals;
    00117                         jrgba_set(&colorvals, 0.30, 1.0, 0.15, 1.0);
    00118                         object_obex_lookup((t_object *)x, gensym("#B"), &box);
    00119                         jbox_set_color(box, &colorvals);
    00120                 }
    00121
    00122                 return (x);
    00123         }
    00124
    00127         void OMax_learn_free(t_OMax_learn *x)
    00128         {
    00129                 ;
    00130         }
    00131
    00134         void OMax_learn_assist(t_OMax_oracle *x, void *b, long io, long index, char *s)
    00135         {
    00136                 switch (io)
    00137                 {
    00138             case 1: // inlets
    00139                                 switch (index)
    00140                         {
    00141                                 case 0: // leftmost
    00142                                         sprintf(s, "messages (add ...)");
    00143                                         break;
    00144                         }
    00145                 break;
    00146                         case 2: // outlets
    00147                                 switch (index)
    00148                         {
    00149                                 case 0: // leftmost
    00150                                         sprintf(s, "state just added");
    00151                                         break;
    00152                         }
    00153                 }
    00154         }
    00155
    00157
    00159
    00160
    00163         t_symbol * OMax_learn_dataname(t_symbol * oname)
    00164         {
    00165                 char dataname[128];
    00166                 strcpy(dataname,oname->s_name);
    00168                 strcat(dataname,"_data");
    00169                 return gensym(dataname);
    00170         }
    00171
    00174         bool OMax_learn_bind(t_OMax_learn *x)
    00175         {
    00177                 if (x->obound == FALSE)
    00178                 {
    00180                         if ((x->oname->s_thing) && (ob_sym(x->oname->s_thing) == gensym("OMax.oracle")))
    00181                         {
    00182                                 x->builder.set_oracle((((t_OMax_oracle*)(x->oname->s_thing))->oracle));
    00183                                 object_post((t_object *)x,"Learner bound to Oracle %s", x->oname->s_name);
    00184                         }
    00185                         else
    00186                         {
    00187                                 object_error((t_object *)x,"No oracle %s declared", x->oname->s_name);
    00188                         }
    00189
    00191                         if ((x->dataname->s_thing) && (ob_sym(x->dataname->s_thing) == gensym("OMax.data")))
    00192                         {
    00193                                 x->builder.set_data((((t_OMax_data*)(x->dataname->s_thing))->data));
    00194                                 x->obound = TRUE;
    00195                                 x->datatype = ((t_OMax_data*)(x->dataname->s_thing))->datatype;
    00196                                 if (x->datatype == SPECTRAL)
    00197                                         x->nbcoeffs = ((t_OMax_data*)(x->dataname->s_thing))->nbcoeffs;
    00198                                 ((t_OMax_data*)(x->dataname->s_thing))->noDelete = FALSE;
    00199                                 object_post((t_object *)x,"Learner bound to Data of Oracle %s", x->oname->s_name);
    00200                         }
    00201                         else
    00202                         {
    00203                                 object_error((t_object *)x,"No data for oracle %s declared", x->oname->s_name);
    00204                         }
    00205                 }
    00206                 // If binding is ok, then don't do it next time.
    00207                 return x->obound;
    00208         }
    00209
    00211
    00213
    00214
    00218         void OMax_learn_add(t_OMax_learn *x, t_symbol *s, short ac, t_atom * av)
    00219         {
    00221                 if (OMax_learn_bind(x))
    00222                 {
    00223                         int out;
    00224                         if (ac>0)
    00225                         {
    00227                                 switch (x->datatype)
    00228                                 {
    00229                                         case LETTERS:
    00230                                         {
    00231                                                 if (av->a_type == A_SYM)
    00232                                                 {
    00233                                                         int statenb;
    00234                                                         O_char newdata (*atom_getsym(av)->s_name);
    00235                                                         statenb = x->builder.get_data()->get_size()-1;
    00236                                                         if (statenb>0)
    00237                                                                 newdata.set_bufferef(statenb);
    00238                                                         else
    00239                                                                 newdata.set_bufferef(0);
    00240                                                         newdata.set_duration(1);
    00241
    00242                                                         ATOMIC_INCREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00243                                                         ATOMIC_INCREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00244                                                         if (!(((t_OMax_oracle *)(x->oname->s_thing))->readcount)
    00245                                                                 && !(((t_OMax_data *)(x->dataname->s_thing))->readcount))
    00246                                                         {
    00248                                                                 out = x->builder.add(newdata);
    00249                                                         }
    00250                                                         else
    00251                                                                 object_error((t_object *)x,"Oracle %s being read (%d, %d)",x->oname->s_name, ((t_OMax_oracle *)(x->oname->s_thing))->readcount, ((t_OMax_data *)(x->dataname->s_thing))->readcount);
    00252                                                         ATOMIC_DECREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00253                                                         ATOMIC_DECREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00254                                                 }
    00255                                                 else
    00256                                                         object_error((t_object *)x,"Wrong type of data");
    00257                                                 break;
    00258
    00259                                         }
    00260                                         case MIDI_MONO:
    00261                                         {
    00262                                                 O_MIDI_mono * newdata = new O_MIDI_mono();
    00263                                                 bool valid = TRUE;
    00264                                                 switch(ac)
    00265                                                 {
    00266                                                         case 6:
    00267                                                                 if ((av+5)->a_type == A_LONG)
    00268                                                                         ((O_label*)newdata)->set_duration(atom_getlong(av+5));
    00269                                                                 else
    00270                                                                 {
    00271                                                                         object_error((t_object *)x, "Error in input, duration must be int");
    00272                                                                         valid = FALSE;
    00273                                                                         break;
    00274                                                                 }
    00275                                                         case 5:
    00276                                                                 if ((av+4)->a_type == A_LONG)
    00277                                                                         ((O_label*)newdata)->set_bufferef(atom_getlong(av+4));
    00278                                                                 else
    00279                                                                 {
    00280                                                                         object_error((t_object *)x, "Error in input, buffer reference must be int");
    00281                                                                         valid = FALSE;
    00282                                                                         break;
    00283                                                                 }
    00284                                                         case 4:
    00285                                                                 if ((av+3)->a_type == A_LONG)
    00286                                                                         ((O_label*)newdata)->set_section(atom_getlong(av+3));
    00287                                                                 else
    00288                                                                 {
    00289                                                                         object_error((t_object *)x, "Error in input, section must be int");
    00290                                                                         valid = FALSE;
    00291                                                                         break;
    00292                                                                 }
    00293                                                         case 3:
    00294                                                                 if ((av+2)->a_type == A_LONG)
    00295                                                                         ((O_label*)newdata)->set_phrase(atom_getlong(av+2));
    00296                                                                 else
    00297                                                                 {
    00298                                                                         object_error((t_object *)x, "Error in input, phrase must be int");
    00299                                                                         valid = FALSE;
    00300                                                                         break;
    00301                                                                 }
    00302                                                         case 2:
    00303                                                                 if ((av+1)->a_type == A_LONG)
    00304                                                                         newdata->set_velocity(atom_getlong(av+1));
    00305                                                                 else
    00306                                                                 {
    00307                                                                         object_error((t_object *)x, "Error in input, velocity must be int");
    00308                                                                         valid = FALSE;
    00309                                                                         break;
    00310                                                                 }
    00311                                                         case 1:
    00312                                                                 if (av->a_type == A_LONG)
    00313                                                                         newdata->set_pitch(atom_getlong(av));
    00314                                                                 else
    00315                                                                 {
    00316                                                                         object_error((t_object *)x, "Error in input, pitch must be int");
    00317                                                                         valid = FALSE;
    00318                                                                 }
    00319                                                                 break;
    00320                                                         default:
    00321                                                                 object_error((t_object *)x, "Error in input, too many arguments");
    00322                                                                 valid = FALSE;
    00323                                                                 break;
    00324                                                 }
    00325                                                 ATOMIC_INCREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00326                                                 ATOMIC_INCREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00327                                                 if (!(((t_OMax_oracle *)(x->oname->s_thing))->readcount)
    00328                                                         && !(((t_OMax_data *)(x->dataname->s_thing))->readcount))
    00329                                                 {
    00331                                                         out = x->builder.add(*newdata);
    00332                                                 }
    00333                                                 else
    00334                                                         object_error((t_object *)x,"Oracle %s being read (%d, %d)",x->oname->s_name, ((t_OMax_oracle *)(x->oname->s_thing))->readcount, ((t_OMax_data *)(x->dataname->s_thing))->readcount);
    00335                                                 ATOMIC_DECREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00336                                                 ATOMIC_DECREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00337                                                 break;
    00338                                         }
    00339                                         case SPECTRAL:
    00340                                                 int pitchin;
    00341                                                 int coeffcount;
    00342                                                 bool valid = TRUE;
    00343                                                 O_spectral * newdata;
    00344                                                 if(ac < (x->nbcoeffs+1)) {
    00345                                                         object_error((t_object *)x, "Missing coefficients");
    00346                                                         valid = FALSE;
    00347                                                 }
    00348                                                 else
    00349                                                 {
    00350                                                         if ((av)->a_type == A_LONG)
    00351                                                                 pitchin = atom_getlong(av);
    00352                                                         else
    00353                                                                 valid = FALSE;
    00354                                                         list<float> coeffsin;
    00355                                                         for (coeffcount = 0; coeffcount < x->nbcoeffs; coeffcount++)
    00356                                                         {
    00357                                                                 if((av+coeffcount+1)->a_type == A_FLOAT)
    00358                                                                         coeffsin.push_back(atom_getfloat(av+coeffcount+1));
    00359                                                                 else {
    00360                                                                         object_error((t_object *)x, "Wrong types in coefficents");
    00361                                                                         valid = FALSE;
    00362                                                                 }
    00363                                                         }
    00364                                                         newdata = new O_spectral(pitchin, coeffsin);
    00365                                                         if (ac >= x->nbcoeffs+2) {
    00366                                                                 if ((av+x->nbcoeffs+1)->a_type == A_LONG)
    00367                                                                         ((O_label*)newdata)->set_phrase(atom_getlong(av+x->nbcoeffs+1));
    00368                                                                 else
    00369                                                                 {
    00370                                                                         object_error((t_object *)x, "Error in input, phrase must be int");
    00371                                                                         valid = FALSE;
    00372                                                                 }
    00373                                                                 if (ac >= x->nbcoeffs+3) {
    00374                                                                         if ((av+x->nbcoeffs+2)->a_type == A_LONG)
    00375                                                                                 ((O_label*)newdata)->set_section(atom_getlong(av+x->nbcoeffs+2));
    00376                                                                         else
    00377                                                                         {
    00378                                                                                 object_error((t_object *)x, "Error in input, section must be int");
    00379                                                                                 valid = FALSE;
    00380                                                                         }
    00381                                                                         if (ac >= x->nbcoeffs+4) {
    00382                                                                                 if ((av+x->nbcoeffs+3)->a_type == A_LONG)
    00383                                                                                         ((O_label*)newdata)->set_bufferef(atom_getlong(av+x->nbcoeffs+3));
    00384                                                                                 else
    00385                                                                                 {
    00386                                                                                         object_error((t_object *)x, "Error in input, buffer reference must be int");
    00387                                                                                         valid = FALSE;
    00388                                                                                 }
    00389                                                                                 if (ac == x->nbcoeffs+5) {
    00390                                                                                         if ((av+x->nbcoeffs+4)->a_type == A_LONG)
    00391                                                                                                 ((O_label*)newdata)->set_duration(atom_getlong(av+x->nbcoeffs+4));
    00392                                                                                         else
    00393                                                                                         {
    00394                                                                                                 object_error((t_object *)x, "Error in input, duration must be int");
    00395                                                                                                 valid = FALSE;
    00396                                                                                         }
    00397
    00398                                                                                 }
    00399                                                                                 else {
    00400                                                                                         object_error((t_object *)x, "Error in input, too many arguments");
    00401                                                                                         valid = FALSE;
    00402                                                                                 }
    00403                                                                         }}}
    00404                                                 }
    00405                                                 ATOMIC_INCREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00406                                                 ATOMIC_INCREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00407                                                 if (!(((t_OMax_oracle *)(x->oname->s_thing))->readcount)
    00408                                                         && !(((t_OMax_data *)(x->dataname->s_thing))->readcount))
    00409                                                 {
    00411                                                         out = x->builder.add(*newdata);
    00412                                                 }
    00413                                                 else
    00414                                                         object_error((t_object *)x,"Oracle %s being read (%d, %d)",x->oname->s_name, ((t_OMax_oracle *)(x->oname->s_thing))->readcount, ((t_OMax_data *)(x->dataname->s_thing))->readcount);
    00415                                                 ATOMIC_DECREMENT(&((t_OMax_oracle *)(x->oname->s_thing))->wflag);
    00416                                                 ATOMIC_DECREMENT(&((t_OMax_data *)(x->dataname->s_thing))->wflag);
    00417                                                 break;
    00418                                 }
    00420                                 outlet_int(x->stateout, out);
    00421                         }
    00422                         else
    00423                                 object_error((t_object *)x,"Error in input, too few arguments");
    00424                 }
    00425         }
    00426
    00428 }
    00429
    00430
    00431 #endif