From faada59567f8cb252f4a909116595ce309ff5828 Mon Sep 17 00:00:00 2001 From: "N.N." Date: Fri, 23 May 2003 12:29:55 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r647, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/miXed/; revision=648 --- cyclone/hammer/urn.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 cyclone/hammer/urn.c (limited to 'cyclone/hammer/urn.c') diff --git a/cyclone/hammer/urn.c b/cyclone/hammer/urn.c new file mode 100644 index 0000000..59b140e --- /dev/null +++ b/cyclone/hammer/urn.c @@ -0,0 +1,148 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER think again about avoiding memory allocation overhead in run-time. + One would need to use a creation argument greater than any future right + inlet value. But this is incompatible (max uses a `static', max-size + array), and should be put somewhere in the docs... */ + +#include "m_pd.h" +#include "common/loud.h" +#include "common/rand.h" +#include "common/grow.h" + +#define URN_INISIZE 128 /* LATER rethink */ +#define URN_MAXSIZE 4096 /* CHECKED */ +#define URN_MAXIMUMSIZE 65536 /* LATER use USHRT_MAX */ + +typedef struct _urn +{ + t_object x_ob; + int x_count; + int x_size; /* as allocated (in bytes) */ + int x_range; /* as used */ + unsigned short *x_urn; + unsigned short x_urnini[URN_INISIZE]; + unsigned int x_seed; + t_outlet *x_bangout; +} t_urn; + +static t_class *urn_class; + +static int urn_resize(t_urn *x, t_float f, int init) +{ + int maxmax = URN_MAXSIZE; + int range = (int)f; /* CHECKED silent truncation */ + if (init) + { + maxmax--; /* CHECKED: max 4095 here (a bug, sort of) */ + /* CHECKED in the constructor this is silent + (also > maxmax clipped without complaining) */ + if (range < 1) + range = 1; + } + else if (range < 1) + { + /* CHECKED (the same for > maxmax) */ + loud_error((t_pd *)x, "illegal size %d", f); + return (0); + } + if (range > URN_MAXIMUMSIZE) + { + loud_warning((t_pd *)x, + "requested size (%d) clipped -- effective size is %d", + range, URN_MAXIMUMSIZE); + range = URN_MAXIMUMSIZE; + } + if (range > maxmax) + loud_incompatible_max(urn_class, maxmax, "elements"); + x->x_range = range; + if (range > x->x_size) + x->x_urn = grow_nodata(&x->x_range, &x->x_size, x->x_urn, + URN_INISIZE, x->x_urnini, + sizeof(*x->x_urn)); + return (1); +} + +static void urn_bang(t_urn *x) +{ + if (x->x_count) + { + int ndx = rand_int(&x->x_seed, x->x_count); + unsigned short pick = x->x_urn[ndx]; + x->x_urn[ndx] = x->x_urn[--x->x_count]; + outlet_float(((t_object *)x)->ob_outlet, pick); + } + /* CHECKED: start banging when the first bang is input + into an empty urn (and not when the last value is output). + CHECKED: keep banging until cleared. */ + else outlet_bang(x->x_bangout); +} + +static void urn_clear(t_urn *x) +{ + int i; + x->x_count = x->x_range; + for (i = 0; i < x->x_count; i++) x->x_urn[i] = i; +} + +static void urn_float(t_urn *x, t_float f) +{ + /* CHECKED: float loudly rejected, int (any value) same as bang */ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) + urn_bang(x); +} + +static void urn_ft1(t_urn *x, t_floatarg f) +{ + if (urn_resize(x, f, 0)) /* CHECKED cleared only if a legal resize */ + urn_clear(x); +} + +static void urn_seed(t_urn *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED */ + if (i < 0) + i = 1; /* CHECKED */ + rand_seed(&x->x_seed, (unsigned int)i); +} + +static void urn_free(t_urn *x) +{ + if (x->x_urn != x->x_urnini) + freebytes(x->x_urn, x->x_size * sizeof(*x->x_urn)); +} + +static void *urn_new(t_floatarg f1, t_floatarg f2) +{ + t_urn *x = (t_urn *)pd_new(urn_class); + x->x_size = URN_INISIZE; + x->x_urn = x->x_urnini; + urn_resize(x, f1, 1); + urn_seed(x, f2); /* CHECKME */ + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + urn_clear(x); + return (x); +} + +void urn_setup(void) +{ + urn_class = class_new(gensym("urn"), + (t_newmethod)urn_new, + (t_method)urn_free, + sizeof(t_urn), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(urn_class, urn_bang); + class_addfloat(urn_class, urn_float); + class_addmethod(urn_class, (t_method)urn_ft1, + gensym("ft1"), A_FLOAT, 0); + /* CHECKED list is auto-unfolded */ + class_addmethod(urn_class, (t_method)urn_seed, + gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */ + class_addmethod(urn_class, (t_method)urn_clear, + gensym("clear"), 0); +} -- cgit v1.2.1