[PD-cvs] externals/moocow/weightmap/src Makefile.am, NONE, 1.1 weightmap-help.pd, NONE, 1.1 weightmap-test.pd, NONE, 1.1 weightmap.c, NONE, 1.1

Bryan Jurish mukau at users.sourceforge.net
Thu Feb 2 13:48:35 CET 2006


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 at 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 = . at PDEXT@

#-----------------------------------------------------------------------
# Flags and variables
#-----------------------------------------------------------------------
PDEXT    = @PDEXT@
EXEEXT   = . at 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 at 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;





More information about the Pd-cvs mailing list