Update of /cvsroot/pure-data/externals/control/choice In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv26382/control/choice
Added Files: choice.c help-choice.pd Log Message: dropped in goodie bag
--- NEW FILE: choice.c --- /* choice -- match incoming list against a collection of stored templates. */
/* Copyright 1999 Miller Puckette. Permission is granted to use this software for any purpose provided you keep this copyright notice intact.
THE AUTHOR AND HIS EMPLOYERS MAKE NO WARRANTY, EXPRESS OR IMPLIED, IN CONNECTION WITH THIS SOFTWARE.
This file is downloadable from http://www.crca.ucsd.edu/~msp . */
#include "m_pd.h" #include <math.h> static t_class *choice_class; #define DIMENSION 10
typedef struct _elem { float e_age; float e_weight[DIMENSION]; } t_elem;
typedef struct _choice { t_object x_obj; t_elem *x_vec; int x_n; int x_nonrepeat; } t_choice;
static void *choice_new(t_float fnonrepeat) { t_choice *x = (t_choice *)pd_new(choice_class); outlet_new(&x->x_obj, gensym("float")); x->x_vec = (t_elem *)getbytes(0); x->x_n = 0; x->x_nonrepeat = (fnonrepeat != 0); return (x); }
static void choice_clear(t_choice *x) { x->x_vec = (t_elem *)resizebytes(x->x_vec, x->x_n * sizeof(t_elem), 0); x->x_n = 0; }
static void choice_print(t_choice *x) { int j; for (j = 0; j < x->x_n; j++) { t_elem *e = x->x_vec + j; t_float *w = e->e_weight; post("%2d age %2d \ w %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f %5.2f", j, (int)(e->e_age), w[0], w[1], w[2], w[3], w[4], w[5], w[6], w[7], w[8], w[9]); } }
static void choice_add(t_choice *x, t_symbol *s, int argc, t_atom *argv) { int oldn = x->x_n, newn = oldn + 1, i; t_elem *e; float sum, normal; x->x_vec = (t_elem *)resizebytes(x->x_vec, oldn * sizeof(t_elem), newn * sizeof(t_elem)); x->x_n = newn; e = x->x_vec + oldn; e->e_age = 2;
for (i = 0, sum = 0; i < DIMENSION; i++) { float f = atom_getfloatarg(i, argc, argv); e->e_weight[i] = f; sum += f*f; } normal = (float)(sum > 0 ? 1./sqrt(sum) : 1); for (i = 0; i < DIMENSION; i++) e->e_weight[i] *= normal; }
static void choice_list(t_choice *x, t_symbol *s, int argc, t_atom *argv) { int i, j; float bestsum = 0; int bestindex = -1; t_float invec[DIMENSION]; for (i = 0; i < DIMENSION; i++) invec[i] = atom_getfloatarg(i, argc, argv); for (j = 0; j < x->x_n; j++) { t_elem *e = x->x_vec + j; float sum; for (i = 0, sum = 0; i < DIMENSION; i++) sum += e->e_weight[i] * invec[i]; if (x->x_nonrepeat) sum *= (float)(log(e->e_age)); if (sum > bestsum) { bestsum = sum; sum = 1; bestindex = j; } } if (bestindex >= 0) { for (j = 0; j < x->x_n; j++) x->x_vec[j].e_age += 1.; x->x_vec[bestindex].e_age = 1; } outlet_float(x->x_obj.ob_outlet, (float)bestindex); }
static void choice_free(t_choice *x) { freebytes(x->x_vec, x->x_n * sizeof(t_elem)); }
void choice_setup(void) { choice_class = class_new(gensym("choice"), (t_newmethod)choice_new, (t_method)choice_free, sizeof(t_choice), 0, A_DEFFLOAT, 0); class_addmethod(choice_class, (t_method)choice_add, gensym("add"), A_GIMME, 0); class_addmethod(choice_class, (t_method)choice_clear, gensym("clear"), 0); class_addmethod(choice_class, (t_method)choice_print, gensym("print"), 0); class_addlist(choice_class, choice_list); }
--- NEW FILE: help-choice.pd --- #N canvas 16 5 609 600 12; #X obj 8 195 choice; #X msg 41 86 print; #X msg 29 63 clear; #X msg 8 34 add 1 0 0 , add 0 1 0 , add 0 0 1 , add 1 1 1 , add 1 1 0; #X obj 77 171 pack 0 0 0; #X floatatom 182 125 0 0 0 0 - - -; #X floatatom 148 125 0 0 0 0 - - -; #X floatatom 115 125 0 0 0 0 - - -; #X obj 77 147 f; #X msg 77 125 bang; #X floatatom 8 216 0 0 0 0 - - -; #X obj 71 196 choice 1; #X floatatom 71 217 0 0 0 0 - - -; #X obj 76 4 choice; #X text 135 3 - search for a best match to an incoming list; #X text 19 243 The choice object holds a list of vectors , each having up to ten elements. When sent a list of numbers , it outputs the index of the known vector that matches most closely. The quality of the match is the dot product of the two vectors after normalizing them , i.e. , the vector whose direction is closest to that of the input wins. ; #X text 19 340 If given a nonzero creation argument , choice tries to avoid repetitious outputs by weighting less recently output vectors preferentially.; #X text 20 389 You can use this to choose interactively between a number of behaviors depending on their attributes. For example , you might have stored a number of melodies , of which some are syncopated , some chromatic , some are more than 100 years old , some are bugle calls , and some are Christmas carols. You could then ask to find a syncopated bugle call (1 , 0 , 0 , 1 , 0) and you'll get the thing most closely matching the request.; #X text 19 514 You can use numbers other than 0 and 1 to indicate relative strengths of the attributes , or even use negative numbers to indicate opposites , either in the incoming lists or in the stored ones.; #X text 320 572 updated for Pd version-0.30; #X text 79 62 delete all stored vectors; #X text 498 34 add vectors; #X text 94 84 debugging printout; #X text 69 104 tweak the numbers and hit "bang" to input a list; #X text 151 197 creation argument to avoid repeated outout; #X text 108 219 output is the index of best match , counting from zero; #X connect 0 0 10 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 2 0 11 0; #X connect 3 0 0 0; #X connect 3 0 11 0; #X connect 4 0 0 0; #X connect 4 0 11 0; #X connect 5 0 4 2; #X connect 6 0 4 1; #X connect 7 0 8 1; #X connect 8 0 4 0; #X connect 9 0 8 0; #X connect 11 0 12 0;