Update of /cvsroot/pure-data/externals/moocow/weightmap/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv24317/src
Added Files: Makefile.am weightmap-help.pd weightmap-test.pd weightmap.c Log Message: initial cvs import
--- NEW FILE: weightmap.c --- /* -*- Mode: C -*- */ /*=============================================================================*\ * File: weightmap.c * Author: Bryan Jurish moocow@ling.uni-potsdam.de * Description: gui-less finer-grained probability-to-integer-map for PD * * - inspired in part by Yves Degoyon's 'probalizer' object *
* * Copyright (c) 2002-2006 Bryan Jurish. * * For information on usage and redistribution, and for a DISCLAIMER OF ALL * WARRANTIES, see the file, "LICENSE.txt," in this distribution. * * 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 2 * of the License, or (at your option) any later version. * * See file LICENSE for further informations on licensing terms. * * 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *=============================================================================*/
#include <m_pd.h>
/* black magic */ #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif
#include <math.h>
#ifdef HAVE_CONFIG_H # include "config.h" #endif
/*-------------------------------------------------------------------- * DEBUG *--------------------------------------------------------------------*/ //#define WEIGHTMAP_DEBUG 1
/*===================================================================== * Constants *=====================================================================*/ #define DEFAULT_WEIGHT_VALUE 0 #define DEFAULT_WEIGHT_MAX 100
/*===================================================================== * Structures and Types *=====================================================================*/
static char *weightmap_banner = "weightmap version %s by Bryan Jurish : map probabilities to associated integers";
static t_class *weightmap_class;
typedef struct _weightmap { t_object x_obj; /* black magic (probably inheritance-related) */ t_float x_wmax; /* maximum expected input weight */ t_int x_nvalues; /* number of stored values */ t_float *x_weights; /* weight of each event (0..x_wmax) */ t_float x_wsum; /* sum of all weights (internal use only) */ t_outlet *x_dumpoutlet; /* outlet for 'dump' messages */ } t_weightmap;
/*-------------------------------------------------------------------- * FLOAT : the guts : handle incoming weights *--------------------------------------------------------------------*/ void weightmap_float(t_weightmap *x, t_floatarg f) { int i; float wt;
// scale weight from (0..x->x_wmax) to (0..x->x_wsum) wt = (f * x->x_wsum) / x->x_wmax;
#ifdef WEIGHTMAP_DEBUG post("weightmap_debug : float : rescale(%f : 0..%f) = %f : 0..%f", f, x->x_wmax, wt, x->x_wsum); #endif
// find match for (i = 0; i < x->x_nvalues; i++) { wt -= x->x_weights[i]; if (wt < 0) { // end of search : outlet current index (counting from 1, for compatibility) outlet_float(x->x_obj.ob_outlet, i+1); return; } } // no matching value found: ouput 0 outlet_float(x->x_obj.ob_outlet, 0); }
/*-------------------------------------------------------------------- * map : set selected values (no resize) *--------------------------------------------------------------------*/ void weightmap_map(t_weightmap *x, t_symbol *s, int argc, t_atom *argv) { int i, idx; float wt;
#ifdef WEIGHTMAP_DEBUG post("weightmap_debug : map : argc=%d", argc); #endif
for (i = 0; i < argc; i += 2) { // get index idx = atom_getint(argv+i); if (idx <= 0 || idx > x->x_nvalues) { // sanity check: index-range error("weightmap : map : index out of range : %d", idx); continue; } idx--;
// get weight-value wt = atom_getfloatarg(i+1, argc, argv);
// adjust sum x->x_wsum += wt - x->x_weights[idx];
// assign weight x->x_weights[idx] = wt; } }
/*-------------------------------------------------------------------- * zero : zero the weight-vector *--------------------------------------------------------------------*/ void weightmap_zero(t_weightmap *x) { int i; // zero all weights for (i = 0; i < x->x_nvalues; i++) { *(x->x_weights+i) = 0; } // reset sum x->x_wsum = 0; }
/*-------------------------------------------------------------------- * set : set the entire weight-vector in one go (with possible resize) *--------------------------------------------------------------------*/ void weightmap_set(t_weightmap *x, t_symbol *s, int argc, t_atom *argv) { int i; float wt;
if (x->x_nvalues != argc) { // set number of elements x->x_nvalues = argc; if ( x->x_nvalues < 1 ) x->x_nvalues = 1;
// (re-)allocate weights if (x->x_weights) { freebytes(x->x_weights, x->x_nvalues*sizeof(t_float)); } x->x_weights = (t_float *)getbytes(x->x_nvalues*sizeof(t_float)); if (!x->x_weights) { error("weightmap : failed to allocate new weight vector"); return; } }
// zero sum x->x_wsum = 0;
// assign new weight-vector for (i = 0; i < x->x_nvalues; i++) { if (i >= argc) { // sanity check: existence x->x_weights[i] = DEFAULT_WEIGHT_VALUE; } else { // normal case: set weight value x->x_weights[i] = atom_getfloat(argv); } x->x_wsum += x->x_weights[i]; argv++; } }
/*-------------------------------------------------------------------- * resize : reset number of values & re-allocate *--------------------------------------------------------------------*/ void weightmap_resize(t_weightmap *x, t_floatarg f) { int i; t_int old_nvalues = x->x_nvalues; t_float *old_weights = x->x_weights;
#ifdef WEIGHTMAP_DEBUG post("weightmap_debug : resize : size=%d", (int)f); #endif
// reset number of elements x->x_nvalues = f; if ( x->x_nvalues < 1 ) x->x_nvalues = 1;
// allocate new weight-vector x->x_weights = (t_float *)getbytes(x->x_nvalues*sizeof(t_float)); if (!x->x_weights) { error("weightmap : resize : failed to allocate new weight vector"); return; }
// zero sum x->x_wsum = 0;
// copy old values for (i = 0; i < x->x_nvalues; i++) { if (i >= old_nvalues) { x->x_weights[i] = DEFAULT_WEIGHT_VALUE; } else { x->x_weights[i] = old_weights[i]; x->x_wsum += old_weights[i]; } }
// free old vector freebytes(old_weights, old_nvalues*sizeof(t_float)); }
/*-------------------------------------------------------------------- * max : set maximum expected input-weight *--------------------------------------------------------------------*/ void weightmap_max(t_weightmap *x, t_floatarg f) { #ifdef WEIGHTMAP_DEBUG post("weightmap_debug : max : max=%f", f); #endif if (f > 0) { x->x_wmax = f; } else { error("weightmap : invalid maximum weight : %f", f); } }
/*-------------------------------------------------------------------- * dump : outputs weight-vector as a list *--------------------------------------------------------------------*/ void weightmap_dump(t_weightmap *x) { int i; float f; t_atom *dumpus;
#ifdef WEIGHTMAP_DEBUG post("weightmap_debug : dump : sum=%f, max=%f", x->x_wsum, x->x_wmax); #endif
// allocate dump-list dumpus = (t_atom *)getbytes(x->x_nvalues*sizeof(t_atom)); if (!dumpus) { error("weightmap : failed to allocate dump list"); return; }
// populate dump-list for (i = 0; i < x->x_nvalues; i++) { f = x->x_weights[i]; SETFLOAT(dumpus+i, f); }
// output dump-list outlet_list(x->x_dumpoutlet, &s_list, x->x_nvalues, dumpus);
}
/*-------------------------------------------------------------------- * new SIZE *--------------------------------------------------------------------*/ static void *weightmap_new(t_floatarg f, t_floatarg max) { t_weightmap *x; int i;
x = (t_weightmap *)pd_new(weightmap_class);
// create float (index) outlet outlet_new(&x->x_obj, &s_float); // create list (dump) outlet x->x_dumpoutlet = outlet_new(&x->x_obj, &s_list);
// set number of elements x->x_nvalues = f; if ( x->x_nvalues < 1 ) x->x_nvalues = 1;
// set maximum expected input probability x->x_wmax = max; if (!x->x_wmax) x->x_wmax = DEFAULT_WEIGHT_MAX;
// allocate weight-vector x->x_weights = (t_float *)getbytes(x->x_nvalues*sizeof(t_float)); if (!x->x_weights) { error("weightmap : failed to allocate weight vector"); return NULL; }
// initialize weights for (i = 0; i < x->x_nvalues; i++) { *(x->x_weights+i) = DEFAULT_WEIGHT_VALUE; } // initialize sum x->x_wsum = DEFAULT_WEIGHT_VALUE * x->x_nvalues;
#ifdef WEIGHTMAP_DEBUG post("weightmap_debug : create : nvalues=%d , wmax=%f", x->x_nvalues, x->x_wmax); #endif
return (void *)x; }
/*-------------------------------------------------------------------- * free *--------------------------------------------------------------------*/ static void weightmap_free(t_weightmap *x) { #ifdef WEIGHTMAP_DEBUG post("weightmap_debug : free"); #endif if (x->x_weights) { freebytes(x->x_weights, x->x_nvalues*sizeof(t_float)); } }
/*-------------------------------------------------------------------- * setup *--------------------------------------------------------------------*/ void weightmap_setup(void) { post(weightmap_banner, PACKAGE_VERSION); weightmap_class = class_new(gensym("weightmap"), /* name */ (t_newmethod)weightmap_new, /* newmethod */ (t_method)weightmap_free, /* freemethod */ sizeof(t_weightmap), /* size */ 0, /* flags */ A_DEFFLOAT, /* ARGLIST: arg1 (size) */ A_DEFFLOAT, /* ARGLIST: arg2 (max) */ 0); /* ARGLIST: END */
class_addmethod(weightmap_class, (t_method)weightmap_float, &s_float, A_FLOAT, 0); class_addmethod(weightmap_class, (t_method)weightmap_map, gensym("map"), A_GIMME, 0); class_addmethod(weightmap_class, (t_method)weightmap_zero, gensym("zero"), 0); class_addmethod(weightmap_class, (t_method)weightmap_set, gensym("set"), A_GIMME, 0); class_addmethod(weightmap_class, (t_method)weightmap_resize, gensym("resize"), A_DEFFLOAT, 0); class_addmethod(weightmap_class, (t_method)weightmap_max, gensym("max"), A_DEFFLOAT, 0); class_addmethod(weightmap_class, (t_method)weightmap_dump, gensym("dump"), 0);
class_sethelpsymbol(weightmap_class, gensym("weightmap-help.pd")); }
--- NEW FILE: weightmap-test.pd --- #N canvas 33 18 810 430 10; #X obj 94 168 weightmap 3; #X msg 154 41 dump; #X obj 215 210 print wm_out2; #X msg 158 63 zero; #X msg 196 41 resize $1; #X floatatom 195 12 5 0 0; #X floatatom 548 33 5 0 0; #X floatatom 598 33 5 0 0; #X obj 548 59 pack 0 0; #X text 549 116 bad input; #X msg 412 11 set 420 24 7; #X msg 549 82 map $1 $2; #X msg 549 132 map 0 1 1 2 2; #X floatatom 106 13 5 0 0; #N canvas 0 0 820 480 statistics 0; #X obj 146 16 inlet; #X msg 169 87 dump; #X msg 63 89 dump; #X obj 170 136 prependany del; #X obj 60 286 outlet; #X obj 274 210 pack 0 0; #X msg 453 127 0; #X obj 324 160 int; #X obj 274 86 t f b f b; #X obj 324 184 + 1; #X obj 306 10 maphash stats; #X obj 170 112 mapread stats; #X obj 62 116 mapread stats; #X obj 340 126 mapread stats; #X obj 274 242 mapwrite stats; #X text 569 30 Total; #X obj 570 121 int 0; #X msg 601 84 0; #X obj 616 121 + 1; #X obj 148 50 route dump clear; #X obj 62 153 unpack 0 0; #X obj 128 181 / 1; #X obj 62 233 pack 0 0 0; #X msg 61 258 $1: $2 = $3%; #X obj 128 207 * 100; #X obj 540 191 int; #X msg 541 226 total = $1; #X msg 519 167 bang; #X connect 0 0 19 0; #X connect 1 0 11 0; #X connect 2 0 12 0; #X connect 3 0 14 0; #X connect 5 0 14 0; #X connect 6 0 7 1; #X connect 7 0 9 0; #X connect 8 0 5 0; #X connect 8 1 7 0; #X connect 8 2 13 0; #X connect 8 3 6 0; #X connect 8 3 16 0; #X connect 9 0 5 1; #X connect 11 0 3 0; #X connect 12 0 20 0; #X connect 13 0 7 1; #X connect 16 0 18 0; #X connect 17 0 16 1; #X connect 17 0 25 1; #X connect 18 0 16 1; #X connect 18 0 25 1; #X connect 19 0 27 0; #X connect 19 0 2 0; #X connect 19 1 1 0; #X connect 19 1 17 0; #X connect 19 2 8 0; #X connect 20 0 22 0; #X connect 20 1 21 0; #X connect 20 1 22 1; #X connect 21 0 24 0; #X connect 22 0 23 0; #X connect 23 0 4 0; #X connect 24 0 22 2; #X connect 25 0 26 0; #X connect 25 0 21 1; #X connect 26 0 4 0; #X connect 27 0 25 0; #X restore 224 293 pd statistics; #X msg 261 260 dump; #X msg 303 260 clear; #X obj 224 325 print stats; #X obj 24 13 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 ; #X obj 24 57 random 100; #X floatatom 49 12 5 0 0; #X obj 335 294 print -----; #X msg 412 37 set 10 20 30 40; #X msg 68 238 0; #X msg 70 268 1; #X obj 24 35 metro 1; #X msg 412 61 set 50 25 25; #X floatatom 285 12 5 0 0; #X msg 286 41 max $1; #X msg 410 85 set 2 1 1; #X obj 6 101 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 ; #X obj 6 145 random 100; #X obj 6 123 metro 1; #X obj 15 168 / 100; #X connect 0 0 14 0; #X connect 0 1 2 0; #X connect 1 0 0 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 5 0 4 0; #X connect 6 0 8 0; #X connect 7 0 8 1; #X connect 8 0 11 0; #X connect 10 0 0 0; #X connect 11 0 0 0; #X connect 12 0 0 0; #X connect 13 0 0 0; #X connect 14 0 17 0; #X connect 15 0 21 0; #X connect 15 0 14 0; #X connect 16 0 14 0; #X connect 18 0 25 0; #X connect 19 0 0 0; #X connect 20 0 25 1; #X connect 22 0 0 0; #X connect 23 0 14 0; #X connect 24 0 14 0; #X connect 25 0 19 0; #X connect 26 0 0 0; #X connect 27 0 28 0; #X connect 28 0 0 0; #X connect 29 0 0 0; #X connect 30 0 32 0; #X connect 31 0 33 0; #X connect 32 0 31 0; #X connect 33 0 0 0;
--- NEW FILE: Makefile.am --- # File: ./src/Makefile.am # Package: weightmap # Description: # + src-level automake file # # Process this file with Automake to create Makefile.in. #-----------------------------------------------------------------------
#----------------------------------------------------------------------- # Options & Subdirectories #-----------------------------------------------------------------------
## --- recursion subdirectories #SUBDIRS =
## --- pseudo-deps for '.SUFFIXES' SUFFIXES = .@PDEXT@
#----------------------------------------------------------------------- # Flags and variables #----------------------------------------------------------------------- PDEXT = @PDEXT@ EXEEXT = .@PDEXT@
#----------------------------------------------------------------------- # pd externals (hacked _PROGRAMS target) #-----------------------------------------------------------------------
## --- externals pdexterns_PROGRAMS = @PD_OBJECT_EXTERNALS@
## --- possible externals EXTRA_PROGRAMS = \ weightmap
## --- patches pdexterns_DATA =
## --- documentation pddoc_DATA = weightmap-help.pd
#----------------------------------------------------------------------- # sources #-----------------------------------------------------------------------
weightmap_SOURCES = \ weightmap.c
#----------------------------------------------------------------------- # external compilation : flags #----------------------------------------------------------------------- DEFS = @DEFS@ AFLAGS = @AFLAGS@ DFLAGS = @DFLAGS@ IFLAGS = @IFLAGS@ LFLAGS = @LFLAGS@ OFLAGS = @OFLAGS@ WFLAGS = -Wall -Winline
#GLIB_IFLAGS = @GLIB_IFLAGS@ #GLIB_LFLAGS = @GLIB_LFLAGS@
AM_CPPFLAGS = $(IFLAGS) $(GLIB_IFLAGS) $(DFLAGS) AM_CFLAGS = $(OFLAGS) $(WFLAGS) $(AFLAGS)
weightmap_LDFLAGS = $(LFLAGS) weightmap_LDADD = $(GLIB_LFLAGS)
#----------------------------------------------------------------------- # Variables: cleanup #----------------------------------------------------------------------- ## --- mostlyclean: built by 'make' & commonly rebuilt #MOSTLYCLEANFILES =
## --- clean: built by 'make' CLEANFILES = *$(EXEEXT)
## --- distclean: built by 'configure' DISTCLEANFILES = \ config.log \ config.cache \ config.status
## -- maintainerclean: built by maintainer / by hand MAINTAINERCLEANFILES = *~ \ $(PODS:.pod=.txt) \ Makefile Makefile.in \ aclocal.m4 \ configure \ install-sh \ stamp-h.in \ config.h.in
maintainer-clean-local: rm -rf autom4te.cache
#CVSCLEAN_SUBDIRS = $(SUBDIRS)
#CVSCLEANFILES = Makefile.in Makefile
#----------------------------------------------------------------------- # Variables: distribution #-----------------------------------------------------------------------
## --- extra distribution files EXTRA_DIST = \ $(pddoc_DATA) \ $(pdexterns_DATA)
## --- recursion subdirectories for 'make dist' DIST_SUBDIRS = $(SUBDIRS)
## --- dist-hook: when another 'Makefile.am' is overkill #DISTHOOK_DIRS = foo #DISTHOOK_FILES = foo/bar.txt foo/baz.txt #dist-hook: # for d in $(DISTHOOK_DIRS); do\ # mkdir -p $(distdir)/$$d ;\ # done # for f in $(DISTHOOK_FILES); do\ # cp -p $(srcdir)/$$f $(distdir)/$$f ;\ # done
#dist-bz2: dist-bzip2 ;
#----------------------------------------------------------------------- # Rules: cleanup #----------------------------------------------------------------------- .PHONY: cvsclean cvsclean-hook
cvsclean: maintainer-clean ;
--- NEW FILE: weightmap-help.pd --- #N canvas 18 0 910 582 10; #X text 33 1 weightmap : map probabilities to associated integers; #X obj 114 364 print wmap_dump; #X obj 8 364 print wmap_out; #X obj 8 338 weightmap 3 100; #X text 463 79 SIZE : number of elements (integer); #X text 429 91 MAXWEIGHT : maximum expected input (float) [default=100] ; #X text 395 65 weightmap SIZE [MAXWEIGHT]; #X text 375 51 SYNTAX:; #X text 373 119 INLETS:; #X text 393 133 1 - floats ("weights" or "probabilities"); #X text 421 147 OR messages; #X text 373 175 OUTLETS:; #X text 391 201 2 - miscellaneous output; #X text 391 187 1 - index (int) of stored weight matching input float ; #X text 377 239 MESSAGES:; #X text 441 313 dump : dump the current weight-vector as a list to outlet-2; #X text 441 293 zero : resets all stored weights to zero; #X text 379 271 max MAXWEIGHT : change maximum expected input probability ; #X msg 63 207 dump; #X msg 67 289 resize 4; #X msg 69 235 max 1; #X msg 69 257 max 100; #X msg 57 177 zero; #X msg 27 75 set 420 24 7; #X msg 33 97 set 50 25 25; #X text 127 85 set entire weight-vector; #X text 107 127 set selected weights; #X text 91 175 reset all weights; #X text 97 207 dump weights to 2nd outlet; #X text 113 239 adjust maximum input-value; #X text 131 297 adjust length of weight-vector; #X msg 67 311 resize 2; #X floatatom 14 44 5 0 0; #X text 63 43 output matching weight index; #X text 371 367 map IDX WEIGHT :; #X text 491 367 associate element IDX (int) of the stored weight-vector with weight WEIGHT (float). Multiple (index , weight) pairs may also be specified.; #X text 393 335 set WEIGHTS :; #X text 600 556 Bryan Jurish moocow@ling.uni-potsdam.de; #X text 393 253 resize SIZE : resizes the weight-vector to SIZE elements ; #X text 491 335 sets the stored weight-vector to WEIGHTS. possibly resizes the vector.; #X text 11 402 NOTES:; #X msg 41 125 map 1 42; #X msg 47 147 map 1 10 2 20 3 30; #X text 11 521 incoming floats are expected to be in the range 0..MAXWEIGHT ; floats which exceed MAXWEIGHT will cause the weightmap to outlet "0 "(zero) , indicating a failed match.; #X text 11 418 weightmap stores a vector of "weights" -- arbitrary floats representing probability values , which are matched against incoming floats to generate integers at the outlet. Greater input floats do not neccesarily correspond to greater stored "weights" , but greater "weights" do cause their associated indices to be output more frequently for random input floats.; #X connect 3 0 2 0; #X connect 3 1 1 0; #X connect 18 0 3 0; #X connect 19 0 3 0; #X connect 20 0 3 0; #X connect 21 0 3 0; #X connect 22 0 3 0; #X connect 23 0 3 0; #X connect 24 0 3 0; #X connect 31 0 3 0; #X connect 32 0 3 0; #X connect 41 0 3 0; #X connect 42 0 3 0;