WoMax Documentation

# PPC/bc.yinstats.c

    00001 /*--------------------------------------
    00002  * bc.stat - bc.stat.c
    00003  * Created on 24/11/09 by Benjamin Levy
    00004  *--------------------------------------*/
    00005
    00006
    00007 #include "ext.h"                                // standard Max include, always required
    00008 #include "ext_obex.h"                   // required for new style Max object
    00009 #include "ext_time.h"
    00010 #include "ext_itm.h"
    00011
    00012
    00013 typedef struct _statelem
    00014         {
    00015                 bool    enable;
    00016                 long    pitch;
    00017                 double  nbOcc;
    00018                 double  nbtot;
    00019                 double  ampacc;
    00020                 double  proba;
    00021                 void*   clock;
    00022                 void*   object;
    00023         } bc_statelem;
    00024
    00025
    00027 typedef struct _bc_yinstats
    00028         {
    00029                 t_object                ob;                             // the object itself (must be first)
    00030                 long                    nbstats;                // number of stat agent
    00031                 bc_statelem*    stats;                  // stat agent vector
    00032                 double                  minproba;               // minimal probabilty
    00033                 long                    window;                 // window for stats (ms)
    00034                 double                  lastpitch;              // last pitch
    00035                 double                  lastamp;                // last amplitude
    00036                 long                    laststat;               // last stat enable
    00037                 void*                   out_pitch;              // outlet 0
    00038                 void*                   out_amp;                // outlet 1
    00039                 void*                   out_proba;              // outlet 2
    00040         } t_bc_yinstats;
    00041
    00043 // prototypes //
    00045
    00046 // Standard Max5 methodes
    00047 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv);
    00048 void bc_yinstats_free(t_bc_yinstats *x);
    00049 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long m, long a, char *s);
    00050
    00051 // Input/ouput routines
    00052 void bc_yinstats_amp(t_bc_yinstats *x, double ampin);
    00053 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin);
    00054 void bc_yinstats_out(bc_statelem *stat);
    00055 void bc_yinstats_stop(t_bc_yinstats *x);
    00056
    00057 // Internal routines
    00058 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin);
    00059 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin);
    00060 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat);
    00061
    00062 // Global class pointer variable
    00063 void *bc_yinstats_class;
    00064
    00065
    00066 int main(void)
    00067 {
    00068         t_class *c;
    00069
    00070         c = class_new("bc.yinstats", (method)bc_yinstats_new, (method)bc_yinstats_free, (long)sizeof(t_bc_yinstats), 0L, A_GIMME, 0);
    00071
    00072         // assistance
    00073     class_addmethod(c, (method)bc_yinstats_assist,"assist",A_CANT, 0);
    00074
    00075         // input methods
    00076         class_addmethod(c, (method)bc_yinstats_pitch, "int", A_LONG, 0);
    00077         class_addmethod(c, (method)bc_yinstats_amp, "ft1", A_FLOAT, 0);
    00078         class_addmethod(c, (method)bc_yinstats_stop, "stop", 0);
    00079
    00080         CLASS_ATTR_LONG(c, "window", 0, t_bc_yinstats, window);
    00081         CLASS_ATTR_LABEL(c, "window", 0, "Window (ms)");
    00082         CLASS_ATTR_SAVE(c, "window", 0);
    00083         CLASS_ATTR_MIN(c, "window", 0, 0);
    00084
    00085         CLASS_ATTR_DOUBLE(c, "minproba", 0, t_bc_yinstats, minproba);
    00086         CLASS_ATTR_LABEL(c, "minproba", 0, "Probability Threshold");
    00087         CLASS_ATTR_SAVE(c, "minproba", 0);
    00088         CLASS_ATTR_FILTER_CLIP(c, "minproba", 0., 1.);
    00089
    00090         class_register(CLASS_BOX, c); /* CLASS_NOBOX */
    00091         bc_yinstats_class = c;
    00092
    00093         return 0;
    00094 }
    00095
    00096 // Object instantiation
    00097 void *bc_yinstats_new(t_symbol *s, long argc, t_atom *argv)
    00098 {
    00099         t_bc_yinstats *x = NULL;
    00100
    00101         // object instantiation, NEW STYLE
    00102         if (x = (t_bc_yinstats *)object_alloc(bc_yinstats_class))
    00103         {
    00104                 // inlets
    00105                 floatin(x, 1); // amplitude
    00106
    00107                 // outlets
    00108                 x->out_proba = floatout(x);
    00109                 x->out_amp = floatout(x);
    00110                 x->out_pitch = intout(x);
    00111
    00112                 x->nbstats = 100;
    00113                 x->minproba = 0.;
    00114
    00115                 // process arguments
    00116                 switch (argc)
    00117                 {
    00118                         /*
    00119                         case 3:
    00120                                 if ((argv + 2)->a_type == A_FLOAT);
    00121                                         x->minproba = atom_getfloat(argv + 2);
    00122                         case 2:
    00123                                 if ((argv + 1)->a_type == A_LONG);
    00124                                         x->window = atom_getlong(argv + 1);
    00125                          */
    00126                         case 1:
    00127                                 if (argv->a_type == A_LONG)
    00128                                         x->nbstats = atom_getlong(argv);
    00129                                 break;
    00130                         default:
    00131                                 object_error((t_object *)x, "Number of stat agents needed");
    00132                 }
    00133
    00134                 // process attributes
    00135                 // override arguments if needed
    00136                 attr_args_process(x, argc, argv);
    00137
    00138                 x->stats = (bc_statelem*)sysmem_newptr(x->nbstats * sizeof(bc_statelem));
    00139                 long i;
    00140                 for (i = 0; i< x->nbstats; i++)
    00141                         bc_yinstats_reset(x, x->stats + i);
    00142                 x->laststat = 0;
    00143         }
    00144         return (x);
    00145 }
    00146
    00147 // Object destruction
    00148 void bc_yinstats_free(t_bc_yinstats *x)
    00149 {
    00150         long i;
    00151         for (i = 0; i< x->nbstats; i++)
    00152         {
    00153                 freeobject(x->stats[i].clock);
    00154         }
    00155         sysmem_freeptr(x->stats);
    00156 }
    00157
    00158 // Inlet/Outlet contextual information when patching in Max5
    00159 void bc_yinstats_assist(t_bc_yinstats *x, void *b, long io, long index, char *s)
    00160 {
    00161         switch (io)
    00162         {
    00163                 case 1: // inlets
    00164                         switch (index)
    00165                 {
    00166                         case 0: // leftmost
    00167                                 sprintf(s, "pitch");
    00168                                 break;
    00169                         case 1:
    00170                                 sprintf(s, "amplitude");
    00171                                 break;
    00172                 }
    00173                         break;
    00174                 case 2: // outlets
    00175                         switch (index)
    00176                 {
    00177                         case 0: // leftmost
    00178                                 sprintf(s, "coocked pitch");
    00179                                 break;
    00180                         case 1:
    00181                                 sprintf(s, "average amplitude");
    00182                                 break;
    00183                         case 2:
    00184                                 sprintf(s,"probability");
    00185                                 break;
    00186                 }
    00187         }
    00188 }
    00189
    00190 void bc_yinstats_amp(t_bc_yinstats *x, double ampin)
    00191 {
    00192         x->lastamp = ampin;
    00193 }
    00194
    00195 void bc_yinstats_pitch(t_bc_yinstats *x, long pitchin)
    00196 {
    00197         x->lastpitch = pitchin;
    00198         bc_yinstats_addocc(x, pitchin, x->lastamp);
    00199         bc_yinstats_addstat(x, pitchin, x->lastamp);
    00200 }
    00201
    00202 bool bc_yinstats_addocc(t_bc_yinstats *x, long pitchin, double ampin)
    00203 {
    00204         long i;
    00205         bool found = FALSE;
    00206         for (i = 0; i<=(x->laststat); i++)
    00207         {
    00208                 if (x->stats[i].enable)
    00209                 {
    00210                         x->stats[i].nbtot++;
    00211                         if (x->stats[i].pitch == pitchin)
    00212                         {
    00213                                 found = TRUE;
    00214                                 x->stats[i].nbOcc++;
    00215                                 x->stats[i].ampacc += ampin;
    00216                         }
    00217                 }
    00218         }
    00219         return found;
    00220 }
    00221
    00222 long bc_yinstats_addstat(t_bc_yinstats *x, long pitchin, double ampin)
    00223 {
    00224         long i = 0;
    00225         while (x->stats[i].enable && i<x->nbstats)
    00226                 i++;
    00227         if (i == x->nbstats)
    00228         {
    00229                 i = 0;
    00230                 object_error((t_object *)x, "too many events");
    00231         }
    00232         x->stats[i].enable = TRUE;
    00233         x->stats[i].pitch = pitchin;
    00234         x->stats[i].ampacc = ampin;
    00235         x->stats[i].nbOcc = 1;
    00236         x->stats[i].nbtot = 1;
    00237         clock_delay(x->stats[i].clock, x->window);
    00238         if (i > (x->laststat))
    00239                 x->laststat = i;
    00240         return i;
    00241 }
    00242
    00243 void bc_yinstats_reset(t_bc_yinstats *x, bc_statelem *stat)
    00244 {
    00245         stat->enable = FALSE;
    00246         stat->pitch = 0;
    00247         stat->ampacc = 0.;
    00248         stat->nbOcc = 0;
    00249         stat->nbtot = 0;
    00250         stat->proba = 0.;
    00251         stat->object = x;
    00252         stat->clock = clock_new(stat , (method)bc_yinstats_out);
    00253 }
    00254
    00255 void bc_yinstats_out(bc_statelem *stat)
    00256 {
    00257         t_bc_yinstats * x = stat->object;
    00258         stat->proba = stat->nbOcc / stat->nbtot;
    00259         if (stat->proba >= x->minproba)
    00260         {
    00261                 outlet_float(x->out_proba, stat->proba);
    00262                 outlet_float(x->out_amp, stat->ampacc / stat->nbOcc);
    00263                 outlet_int(x->out_pitch, stat->pitch);
    00264         }
    00265         stat->enable = FALSE;
    00266 }
    00267
    00268 void bc_yinstats_stop(t_bc_yinstats *x)
    00269 {
    00270         long i;
    00271         for (i = 0; i< x->laststat; i++)
    00272         {
    00273                 x->stats[i].enable = FALSE;
    00274                 clock_unset(x->stats[i].clock);
    00275         }
    00276         x->laststat = 0;
    00277 }