From 17ec1deb74e2e934dc11fb4d9a2f8c6cef34c5a7 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Mon, 9 Jul 2007 20:45:58 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r7949, which included commits to RCS files with non-trunk default branches. svn path=/trunk/externals/moonlib/; revision=7950 --- .directory | 47 ++ Makefile | 18 + README.txt | 113 +++ XFS.txt | 1 + absolutepath.c | 140 ++++ basedir.c | 72 ++ char2f.c | 53 ++ comma.c | 53 ++ dinlet~.c | 136 ++++ dispatch.c | 194 ++++++ dripchar.c | 82 +++ f2char.c | 53 ++ gamme.c | 558 +++++++++++++++ help/absolutepath-help.pd | 13 + help/basedir-help.pd | 18 + help/char2f-help.pd | 18 + help/comma-help.pd | 40 ++ help/d/d0.gif | Bin 0 -> 231 bytes help/d/d1.gif | Bin 0 -> 232 bytes help/d/d10.gif | Bin 0 -> 239 bytes help/d/d11.gif | Bin 0 -> 238 bytes help/d/d12.gif | Bin 0 -> 236 bytes help/d/d13.gif | Bin 0 -> 237 bytes help/d/d14.gif | Bin 0 -> 237 bytes help/d/d15.gif | Bin 0 -> 239 bytes help/d/d16.gif | Bin 0 -> 238 bytes help/d/d17.gif | Bin 0 -> 234 bytes help/d/d18.gif | Bin 0 -> 232 bytes help/d/d19.gif | Bin 0 -> 239 bytes help/d/d2.gif | Bin 0 -> 237 bytes help/d/d20.gif | Bin 0 -> 240 bytes help/d/d21.gif | Bin 0 -> 236 bytes help/d/d22.gif | Bin 0 -> 236 bytes help/d/d23.gif | Bin 0 -> 236 bytes help/d/d24.gif | Bin 0 -> 236 bytes help/d/d25.gif | Bin 0 -> 234 bytes help/d/d26.gif | Bin 0 -> 234 bytes help/d/d27.gif | Bin 0 -> 236 bytes help/d/d28.gif | Bin 0 -> 235 bytes help/d/d29.gif | Bin 0 -> 234 bytes help/d/d3.gif | Bin 0 -> 234 bytes help/d/d30.gif | Bin 0 -> 233 bytes help/d/d31.gif | Bin 0 -> 233 bytes help/d/d32.gif | Bin 0 -> 238 bytes help/d/d33.gif | Bin 0 -> 233 bytes help/d/d34.gif | Bin 0 -> 236 bytes help/d/d35.gif | Bin 0 -> 233 bytes help/d/d36.gif | Bin 0 -> 235 bytes help/d/d37.gif | Bin 0 -> 236 bytes help/d/d38.gif | Bin 0 -> 237 bytes help/d/d39.gif | Bin 0 -> 236 bytes help/d/d4.gif | Bin 0 -> 231 bytes help/d/d40.gif | Bin 0 -> 237 bytes help/d/d41.gif | Bin 0 -> 235 bytes help/d/d42.gif | Bin 0 -> 238 bytes help/d/d43.gif | Bin 0 -> 236 bytes help/d/d44.gif | Bin 0 -> 230 bytes help/d/d45.gif | Bin 0 -> 235 bytes help/d/d46.gif | Bin 0 -> 236 bytes help/d/d47.gif | Bin 0 -> 235 bytes help/d/d48.gif | Bin 0 -> 240 bytes help/d/d49.gif | Bin 0 -> 236 bytes help/d/d5.gif | Bin 0 -> 238 bytes help/d/d50.gif | Bin 0 -> 237 bytes help/d/d51.gif | Bin 0 -> 236 bytes help/d/d52.gif | Bin 0 -> 234 bytes help/d/d53.gif | Bin 0 -> 239 bytes help/d/d54.gif | Bin 0 -> 238 bytes help/d/d55.gif | Bin 0 -> 240 bytes help/d/d56.gif | Bin 0 -> 235 bytes help/d/d57.gif | Bin 0 -> 236 bytes help/d/d58.gif | Bin 0 -> 236 bytes help/d/d59.gif | Bin 0 -> 236 bytes help/d/d6.gif | Bin 0 -> 236 bytes help/d/d60.gif | Bin 0 -> 235 bytes help/d/d61.gif | Bin 0 -> 236 bytes help/d/d62.gif | Bin 0 -> 235 bytes help/d/d63.gif | Bin 0 -> 229 bytes help/d/d7.gif | Bin 0 -> 237 bytes help/d/d8.gif | Bin 0 -> 240 bytes help/d/d9.gif | Bin 0 -> 237 bytes help/dinlet~-help.pd | 37 + help/dispatch-help.pd | 65 ++ help/dripchar-help.pd | 28 + help/f2char-help.pd | 18 + help/f2s-help.pd | 17 + help/gamme-help.pd | 171 +++++ help/image-help.pd | 104 +++ help/joystik-help.pd | 44 ++ help/makecolor-help.pd | 18 + help/mknob-help.pd | 53 ++ help/panvol~-help.pd | 34 + help/pause.gif | Bin 0 -> 61 bytes help/play.gif | Bin 0 -> 58 bytes help/playy.gif | Bin 0 -> 58 bytes help/popen-help.pd | 68 ++ help/readsfv~-help.pd | 60 ++ help/rec.gif | Bin 0 -> 58 bytes help/relativepath-help.pd | 13 + help/s2f-help.pd | 18 + help/sarray-help.pd | 93 +++ help/saww.gif | Bin 0 -> 61 bytes help/sfread2~-help.pd | 60 ++ help/sin.gif | Bin 0 -> 58 bytes help/sinw.gif | Bin 0 -> 61 bytes help/slist-help.pd | 61 ++ help/squarew.gif | Bin 0 -> 61 bytes help/ssaw~-help.pd | 21 + help/tabdump2-help.pd | 31 + help/tabenv-help.pd | 25 + help/tabreadl-help.pd | 26 + help/tabsort-help.pd | 32 + help/tabsort2-help.pd | 84 +++ image.c | 306 +++++++++ joystik.c | 191 +++++ mknob.c | 870 +++++++++++++++++++++++ panvol~.c | 119 ++++ popen.c | 211 ++++++ readsfv~.c | 1683 +++++++++++++++++++++++++++++++++++++++++++++ relativepath.c | 146 ++++ s2f.c | 53 ++ sarray.c | 264 +++++++ sfread2~.c | 410 +++++++++++ slist.c | 233 +++++++ ssaw~.c | 213 ++++++ tabdump2.c | 120 ++++ tabenv.c | 294 ++++++++ tabreadl.c | 84 +++ tabsort.c | 124 ++++ tabsort2.c | 164 +++++ wac.c | 253 +++++++ 131 files changed, 8528 insertions(+) create mode 100644 .directory create mode 100644 Makefile create mode 100644 README.txt create mode 100644 XFS.txt create mode 100644 absolutepath.c create mode 100644 basedir.c create mode 100644 char2f.c create mode 100644 comma.c create mode 100644 dinlet~.c create mode 100644 dispatch.c create mode 100644 dripchar.c create mode 100644 f2char.c create mode 100644 gamme.c create mode 100644 help/absolutepath-help.pd create mode 100644 help/basedir-help.pd create mode 100644 help/char2f-help.pd create mode 100644 help/comma-help.pd create mode 100644 help/d/d0.gif create mode 100644 help/d/d1.gif create mode 100644 help/d/d10.gif create mode 100644 help/d/d11.gif create mode 100644 help/d/d12.gif create mode 100644 help/d/d13.gif create mode 100644 help/d/d14.gif create mode 100644 help/d/d15.gif create mode 100644 help/d/d16.gif create mode 100644 help/d/d17.gif create mode 100644 help/d/d18.gif create mode 100644 help/d/d19.gif create mode 100644 help/d/d2.gif create mode 100644 help/d/d20.gif create mode 100644 help/d/d21.gif create mode 100644 help/d/d22.gif create mode 100644 help/d/d23.gif create mode 100644 help/d/d24.gif create mode 100644 help/d/d25.gif create mode 100644 help/d/d26.gif create mode 100644 help/d/d27.gif create mode 100644 help/d/d28.gif create mode 100644 help/d/d29.gif create mode 100644 help/d/d3.gif create mode 100644 help/d/d30.gif create mode 100644 help/d/d31.gif create mode 100644 help/d/d32.gif create mode 100644 help/d/d33.gif create mode 100644 help/d/d34.gif create mode 100644 help/d/d35.gif create mode 100644 help/d/d36.gif create mode 100644 help/d/d37.gif create mode 100644 help/d/d38.gif create mode 100644 help/d/d39.gif create mode 100644 help/d/d4.gif create mode 100644 help/d/d40.gif create mode 100644 help/d/d41.gif create mode 100644 help/d/d42.gif create mode 100644 help/d/d43.gif create mode 100644 help/d/d44.gif create mode 100644 help/d/d45.gif create mode 100644 help/d/d46.gif create mode 100644 help/d/d47.gif create mode 100644 help/d/d48.gif create mode 100644 help/d/d49.gif create mode 100644 help/d/d5.gif create mode 100644 help/d/d50.gif create mode 100644 help/d/d51.gif create mode 100644 help/d/d52.gif create mode 100644 help/d/d53.gif create mode 100644 help/d/d54.gif create mode 100644 help/d/d55.gif create mode 100644 help/d/d56.gif create mode 100644 help/d/d57.gif create mode 100644 help/d/d58.gif create mode 100644 help/d/d59.gif create mode 100644 help/d/d6.gif create mode 100644 help/d/d60.gif create mode 100644 help/d/d61.gif create mode 100644 help/d/d62.gif create mode 100644 help/d/d63.gif create mode 100644 help/d/d7.gif create mode 100644 help/d/d8.gif create mode 100644 help/d/d9.gif create mode 100644 help/dinlet~-help.pd create mode 100644 help/dispatch-help.pd create mode 100644 help/dripchar-help.pd create mode 100644 help/f2char-help.pd create mode 100644 help/f2s-help.pd create mode 100644 help/gamme-help.pd create mode 100644 help/image-help.pd create mode 100644 help/joystik-help.pd create mode 100644 help/makecolor-help.pd create mode 100644 help/mknob-help.pd create mode 100644 help/panvol~-help.pd create mode 100644 help/pause.gif create mode 100644 help/play.gif create mode 100644 help/playy.gif create mode 100644 help/popen-help.pd create mode 100644 help/readsfv~-help.pd create mode 100644 help/rec.gif create mode 100644 help/relativepath-help.pd create mode 100644 help/s2f-help.pd create mode 100644 help/sarray-help.pd create mode 100644 help/saww.gif create mode 100644 help/sfread2~-help.pd create mode 100644 help/sin.gif create mode 100644 help/sinw.gif create mode 100644 help/slist-help.pd create mode 100644 help/squarew.gif create mode 100644 help/ssaw~-help.pd create mode 100644 help/tabdump2-help.pd create mode 100644 help/tabenv-help.pd create mode 100644 help/tabreadl-help.pd create mode 100644 help/tabsort-help.pd create mode 100644 help/tabsort2-help.pd create mode 100644 image.c create mode 100644 joystik.c create mode 100644 mknob.c create mode 100644 panvol~.c create mode 100644 popen.c create mode 100644 readsfv~.c create mode 100644 relativepath.c create mode 100644 s2f.c create mode 100644 sarray.c create mode 100644 sfread2~.c create mode 100644 slist.c create mode 100644 ssaw~.c create mode 100644 tabdump2.c create mode 100644 tabenv.c create mode 100644 tabreadl.c create mode 100644 tabsort.c create mode 100644 tabsort2.c create mode 100644 wac.c diff --git a/.directory b/.directory new file mode 100644 index 0000000..30a00cb --- /dev/null +++ b/.directory @@ -0,0 +1,47 @@ +[IconPosition::README] +X=456 +Y=60 + +[IconPosition::docs] +X=28 +Y=5 + +[IconPosition::externs] +X=113 +Y=5 + +[IconPosition::externs0.37] +X=190 +Y=5 + +[IconPosition::makefile] +X=287 +Y=60 + +[IconPosition::nilib_0.1.0] +X=281 +Y=5 + +[IconPosition::nilib_0.2.0] +X=368 +Y=5 + +[IconPosition::others_0.2] +X=453 +Y=5 + +[IconPosition::paths.txt] +X=370 +Y=60 + +[IconPosition::sublib_0.1.0] +X=16 +Y=60 + +[IconPosition::sublib_0.2.0] +X=103 +Y=60 + +[IconPosition::sublib_0.3.0] +X=190 +Y=60 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..ae29994 --- /dev/null +++ b/Makefile @@ -0,0 +1,18 @@ +TARGET := $(shell pwd | sed 's|.*/\(.*\)$$|\1|') +EXTERNALS_ROOT := $(shell pwd | sed 's|^\(/.*externals\).*|\1|') + +default: + make -C $(EXTERNALS_ROOT) $(TARGET) + +install: + make -C $(EXTERNALS_ROOT) $(TARGET)_install + +clean: + make -C $(EXTERNALS_ROOT) $(TARGET)_clean + +test_locations: + make -C $(EXTERNALS_ROOT) test_locations + +etags: + etags *.[ch] $(EXTERNALS_ROOT)/../pd/src/*.[ch] /usr/include/*.h \ + /usr/include/*/*.h diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..e4e5d5a --- /dev/null +++ b/README.txt @@ -0,0 +1,113 @@ +Here are the libs I've written for Pd. +They can be splitted in three parts: + + 1. the nilib library, which is a kind of wrapper between Pd and Gtk, and its + objects: + nifs (a one-click file selector, with some special tricks...), niscope (a + simple oscilloscope), and nileon (a simple drum machine, but it's the + replication of an enormous mechanical one, named Leon Napakatbra, which was + built from a 8 meters diameter merry-go-round...). + There was also nimouse (giving mouse position/buttons) and nitab (the same + for wacom serial graphire tablet) but i don't use these anymore: it's too + dangerous to access a device file directly from pd. Beter use gtkmouse and + wac/wacusb programs with pdsend/pdreceive. + + 2. the sub library, which is a collection of gui control objects (subdial, + subslider, subbang and subtoggle) that are placed into a subpatch but are + visible in the parent window, into the subpatch's box. The idea was to build + easy-to-use complex subpatchs, or abstractions. I wrote it before + "graph-on-parent" was implemented in Pd, so it's a bit deprecated now, but + it has the advantage that subs values (positions of the buttons) are saved + into the parent patch... very useful in case of abstractions. + About of these questions, have a look to my AutoPreset abstractions, which + adds a manner to save the value of regular gui objects (hslider etc...) into + either a file or the parent patch, even those nested in abstractions (and + recursively in abstractions of abstractions...). It works also with tables, + symbols and symbol arrays. + + 3. some other objects, such as: + + tabenv : like env~, an enveloppe follower, but computing on a table, so + possibly much speeder than real-time env~'s computation. + tabsort and tabsort2 : returns the indices of the sorted table (tabsort2 + is bidimentionnal). + gamme : one octave of a piano keyboard used to filter/choose notes in a + selected scale. + absolutepath/relativepath : to use datas (sounds, texts, presets, images, + programs...) nested in the patch's directory (and in subdirs). + sarray and slist : to creates shared dynamic arrays or lists with symbols. + sfread2~ and readsfv~ : to pitch the direct-from-disk reading of sound files. + dinlet~ : an inlet~ with a default value (when nothing is connected to it). + mknob : a round knob ala iemgui vslider (with its "properties" window). + dispatch : creates one bus name for many buttons' buses: from the N pairs + (slider1-snd/slider1-rcv) ... (sliderN-snd/sliderN-rcv), creates only + one pair of buses named (slider-snd/slider-rcv) , in which datas are + prepended by the number of the "sub-bus". + joystik : an improvment of Joseph A. Sarlo's joystick. + image : an improvment of Guenter Geiger's one. Same name, but it's + compatible. Here you can share images through different objects, preload + a list of images, and animate this list. + + and some others... + +CAUTION: + + This stuff was written with Pd v0.34-4 to v0.37 on a PC under Linux. It + hasn't be tested under other conditions; nilib will only work under Linux + (but I think it will be OK on other machines than PC), because of use of + multithreading and GTK . + Anyway makefiles are only working for Linux for the moment... + Moreover I think sub library is potentially very sensible to possible + modifications of Pd sources. + + + +To install: + +sublib_0.1.0 is for Pd 0.33 +sublib_0.2.0 is for Pd 0.35 +sublib_0.3.0 is for Pd 0.37 + +nilib_0.1.0 is for Pd 0.35 +nilib_0.2.0 is for Pd 0.37 + +others_0.1.0 is for Pd 0.35 +others_0.2.0 is for Pd 0.37 + + + +Edit paths.txt to tune install paths and pure-data's location. +Edit this makefile if you want to select older versions of externals (if you + are using pd0.37 it should be ok). + +Then: + +make +make install + + + +If you keep externals locally inside moonlibs directory, then you should add it +to your pdrc file: + +-path moonlibs-0.2/externs +-helppath moonlibs-0.2/docs + + +CAUTION : + 1) (pd 0.35) You MUST fix a bug pd sources and recompile them in order to have + dinlet~ working !! + You have to replace the function obj_findsignalscalar() in file m_obj.c + by the one written in dinlet~.c . + + (dinlet~ is a signal inlet where you can choose the default float value it + outputs when no signal is connected into.) + + + 2) In order to have sfread~ working with big files in direct-from-disk + mode you have to hack pd sources: change + mlockall(MCL_FUTURE) + with + mlockall(MCL_CURRENT) + in s_linux.c (pd0.35) or s_inter.c (pd0.37). If not the whole file will be loaded in memory when + opening it. diff --git a/XFS.txt b/XFS.txt new file mode 100644 index 0000000..d50aece --- /dev/null +++ b/XFS.txt @@ -0,0 +1 @@ +xfs -port -1 -daemon -droppriv -user xfs diff --git a/absolutepath.c b/absolutepath.c new file mode 100644 index 0000000..3e75df6 --- /dev/null +++ b/absolutepath.c @@ -0,0 +1,140 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include */ +#include "m_pd.h" +#include "g_canvas.h" + +#include +#include +#include +#include +#include +#include + +extern t_canvas *canvas_list; /* list of all root canvases */ +extern int canvas_getdollarzero( void); + +struct _canvasenvironment +{ + t_symbol *ce_dir; /* directory patch lives in */ + int ce_argc; /* number of "$" arguments */ + t_atom *ce_argv; /* array of "$" arguments */ + int ce_dollarzero; /* value of "$0" */ +}; + +typedef struct _absolutepath +{ + t_object x_obj; + t_canvas *x_canvas; + int x_dolzero; + int x_realized; +}t_absolutepath; + +t_class *absolutepath_class; + +void absolutepath_setup(void); + +static t_glist *getcanvas(t_glist *can,int d0) +{ + t_canvas *retcan=0; + t_gobj *ob; + + if((can->gl_env)&&(can->gl_env->ce_dollarzero==d0)){ + return can; + } + + ob=can->gl_list; + while(ob&&(retcan==0)) { + if (pd_class(&ob->g_pd) == canvas_class) + retcan=getcanvas((t_glist *)ob,d0); + ob=ob->g_next; + } + + if((!retcan)&&(can->gl_next)) retcan=getcanvas((t_glist *)can->gl_next,d0); + return retcan; +} + + +static void absolutepath_symbol(t_absolutepath *x,t_symbol *sym) +{ + t_canvas *can=0; + char buf[MAXPDSTRING], *bufptr, + *instr=sym->s_name, + canname[MAXPDSTRING],totaldir[MAXPDSTRING], + *cnamedir, + *candir; + unsigned int n,i=0; + int fd; + + if(!x->x_realized) can=(t_canvas*)getcanvas(canvas_list,x->x_dolzero); + if(can) { + x->x_canvas = can; + x->x_realized = 1; + //post("found $0 canvas : %x %d ",x->x_canvas, x->x_canvas->gl_env->ce_dollarzero ); + } + + if(!instr) return; + + candir=canvas_getdir(x->x_canvas)->s_name; + if(!candir) candir=""; + + //post("input= %s candir= %s glname=%s",instr,candir,x->x_canvas->gl_name->s_name); + + strcpy(canname,x->x_canvas->gl_name->s_name); + cnamedir=dirname(canname); + + if (strcmp(cnamedir,".")) { + sprintf(totaldir,"%s/%s",candir,cnamedir); + fd=open_via_path(totaldir,instr ,"",buf, &bufptr, MAXPDSTRING, 1); + } + else + fd=open_via_path(candir, instr, "",buf, &bufptr, MAXPDSTRING, 1); + + if (fd>=0) { + close(fd); + buf[strlen(buf)]='/'; + outlet_symbol(x->x_obj.ob_outlet,gensym(buf)); + } + return; +} + + +static void *absolutepath_new(t_float dolzero) +{ + t_absolutepath *x = (t_absolutepath *)pd_new(absolutepath_class); + t_canvas *can=canvas_list; + int d0; + + outlet_new(&x->x_obj, 0); + x->x_canvas = canvas_getcurrent(); + x->x_dolzero = dolzero; + x->x_realized=dolzero?0:1; + + return (void *)x; +} + +void absolutepath_setup(void) +{ + absolutepath_class = class_new(gensym("absolutepath"),(t_newmethod)absolutepath_new, + 0, sizeof(t_absolutepath), 0,A_DEFFLOAT, 0); + + class_addsymbol(absolutepath_class, absolutepath_symbol); +} + diff --git a/basedir.c b/basedir.c new file mode 100644 index 0000000..ad2f4f6 --- /dev/null +++ b/basedir.c @@ -0,0 +1,72 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include */ +#include "m_pd.h" + +#include +#include +#include +#include +#include +#include + +typedef struct _basedir +{ + t_object x_obj; +}t_basedir; + +t_class *basedir_class; + +void basedir_setup(void); + +static void basedir_symbol(t_basedir *x,t_symbol *sym) +{ + static t_binbuf *binbuf=0; + t_atom at[2]; + char *b,*d; + int l; + + if(!sym->s_name) return; + + b=strdup(sym->s_name); + d=strdup(sym->s_name); + + SETSYMBOL(&at[0],gensym(basename(b))); + SETSYMBOL(&at[1],gensym(dirname(d))); + + outlet_list(x->x_obj.ob_outlet,0,2,at); +} + + +static void *basedir_new(void) +{ + t_basedir *x = (t_basedir *)pd_new(basedir_class); + outlet_new(&x->x_obj, 0); + return (void *)x; +} + +void basedir_setup(void) +{ + basedir_class = class_new(gensym("basedir"),(t_newmethod)basedir_new, + 0, sizeof(t_basedir), 0, 0); + + class_addsymbol(basedir_class, basedir_symbol); +} + diff --git a/char2f.c b/char2f.c new file mode 100644 index 0000000..ef8af99 --- /dev/null +++ b/char2f.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + + +typedef struct _char2f +{ + t_object x_obj; +}t_char2f; + +t_class *char2f_class; + +void char2f_setup(void); + +static void char2f_symbol(t_char2f *x,t_symbol *sym) +{ + if(!sym->s_name) return; + + outlet_float(x->x_obj.ob_outlet,(float)sym->s_name[0]); +} + +static void *char2f_new(void) +{ + t_char2f *x = (t_char2f *)pd_new(char2f_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void char2f_setup(void) +{ + char2f_class = class_new(gensym("char2f"),(t_newmethod)char2f_new, + 0, sizeof(t_char2f), 0, 0); + + class_addsymbol(char2f_class, char2f_symbol); +} + diff --git a/comma.c b/comma.c new file mode 100644 index 0000000..737d2b7 --- /dev/null +++ b/comma.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + +static t_atom _commaatom_; + +typedef struct _comma +{ + t_object x_obj; +}t_comma; + +t_class *comma_class; + +void comma_setup(void); + +static void comma_bang(t_comma *x) +{ + outlet_list(x->x_obj.ob_outlet, &s_list, 1, &_commaatom_); +} + +static void *comma_new(void) +{ + t_comma *x = (t_comma *)pd_new(comma_class); + outlet_new(&x->x_obj,&s_symbol); + return (void *)x; +} + +void comma_setup(void) +{ + comma_class = class_new(gensym("comma"),(t_newmethod)comma_new, + 0, sizeof(t_comma), 0, 0); + + class_addbang(comma_class, comma_bang); + SETCOMMA(&_commaatom_); +} + diff --git a/dinlet~.c b/dinlet~.c new file mode 100644 index 0000000..dc7f260 --- /dev/null +++ b/dinlet~.c @@ -0,0 +1,136 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* this file is made from parts of m_object.c and g_io.c +* it defines a signal inlet named dinlet~ which is the same as inlet~ +* exepts you can give a default float value for the case none signal +* is connected to this inlet~. */ + +/***********************************************************************/ +/* CAUTION : + You MUST fix a bug pd sources and recompile them in order to have + dinlet~ working !! + + this function must be fixed in pd/m_obj.c: */ +#if 0 +t_sample *obj_findsignalscalar(t_object *x, int m) +{ + int n = 0,mbak=m; + t_inlet *i; + post("my obj_findsignalscalar"); + if (x->ob_pd->c_firstin && x->ob_pd->c_floatsignalin) + { + if (!m--) + return (x->ob_pd->c_floatsignalin > 0 ? + (t_sample *)(((char *)x) + x->ob_pd->c_floatsignalin) : 0); + n++; + } + for (i = x->ob_inlet; i; i = i->i_next, m--) + if (i->i_symfrom == &s_signal) + { + /*if (m == 0)*/ + if(n==mbak) + return (&i->i_un.iu_floatsignalvalue); + n++; + } + return (0); +} +#endif +/***********************************************************************/ + +#include "m_pd.h" +#include "m_imp.h" +#include "g_canvas.h" +#include + +/******************** from m_obj.c: **************************/ +/* only because inlet_float() is not public... */ +union inletunion +{ + t_symbol *iu_symto; + t_gpointer *iu_pointerslot; + t_float *iu_floatslot; + t_symbol **iu_symslot; + t_sample iu_floatsignalvalue; +}; + +struct _inlet +{ + t_pd i_pd; + struct _inlet *i_next; + t_object *i_owner; + t_pd *i_dest; + t_symbol *i_symfrom; + union inletunion i_un; +}; + +#define i_symto i_un.iu_symto + +static void dinlet_float(t_inlet *x, t_float f) +{ + if (x->i_symfrom == &s_float) + pd_vmess(x->i_dest, x->i_symto, "f", (t_floatarg)f); + else if (x->i_symfrom == &s_signal) + x->i_un.iu_floatsignalvalue = f; + else if (!x->i_symfrom) + pd_float(x->i_dest, f); + /*else inlet_wrong(x, &s_float);*/ +} +/**************** from g_io.c : *********************************/ + +void signal_setborrowed(t_signal *sig, t_signal *sig2); +void signal_makereusable(t_signal *sig); + +/* ------------------------- vinlet -------------------------- */ +t_class *vinlet_class; + +typedef struct _vinlet +{ + t_object x_obj; + t_canvas *x_canvas; + t_inlet *x_inlet; + int x_bufsize; + t_float *x_buf; /* signal buffer; zero if not a signal */ + t_float *x_endbuf; + t_float *x_fill; + t_float *x_read; + int x_hop; + /* if not reblocking, the next slot communicates the parent's inlet + signal from the prolog to the DSP routine: */ + t_signal *x_directsignal; +} t_vinlet; + + +static void *dinlet_newsig(t_floatarg f) +{ + t_vinlet *x = (t_vinlet *)pd_new(vinlet_class); + x->x_canvas = canvas_getcurrent(); + x->x_inlet = canvas_addinlet(x->x_canvas, &x->x_obj.ob_pd, &s_signal,0); + x->x_endbuf = x->x_buf = (t_float *)getbytes(0); + x->x_bufsize = 0; + x->x_directsignal = 0; + x->x_inlet->i_un.iu_floatsignalvalue=f; + outlet_new(&x->x_obj, &s_signal); + return (x); +} + +void dinlet_tilde_setup(void) +{ + class_addcreator((t_newmethod)dinlet_newsig, gensym("dinlet~"), A_DEFFLOAT,0); +} diff --git a/dispatch.c b/dispatch.c new file mode 100644 index 0000000..f8a937a --- /dev/null +++ b/dispatch.c @@ -0,0 +1,194 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol array, ala "value" .*/ + +#include "m_pd.h" +#include +#include +#include + +static t_class *dispatch_class, *dispsnd_class; +static t_symbol *s__; + +typedef struct _dispatch t_dispatch; + +typedef struct dispsnd +{ + t_pd d_pd; + t_symbol *d_eachsnd; + t_symbol *d_allsnd; + t_int d_num; +} t_dispsnd; + +struct _dispatch +{ + t_object x_obj; + t_symbol *x_sym; + int x_from; + int x_to; + + t_dispsnd **x_snds; + + t_symbol *x_allrcv; + t_symbol **x_eachrcvs; +}; + +/*--------------------- dispsnd ------------------------------------*/ + +static void dispsnd_ff(t_dispsnd *x) +{ + pd_unbind((t_pd*)x, x->d_eachsnd); +} + +static void *dispsnd_new(t_symbol *eachsnd,t_symbol *allsnd,int num) +{ + t_dispsnd *x = (t_dispsnd *)pd_new(dispsnd_class); + + //post("new dispsnd: num=%d rcv=%s snd=%s",num,eachsnd->s_name,allsnd->s_name); + x->d_eachsnd=eachsnd; + x->d_allsnd=allsnd; + x->d_num=num; + + pd_bind((t_pd*)x, x->d_eachsnd); + + return (x); +} + +static void dispsnd_float(t_dispsnd *x, t_float f) +{ + t_atom out[2]; + + if (x->d_allsnd->s_thing) { + SETFLOAT(&out[0],x->d_num); + SETFLOAT(&out[1],f); + + typedmess(x->d_allsnd->s_thing, &s_list, 2, out); + } +} + +static void dispsnd_anything(t_dispsnd *x, t_symbol *s, int argc, t_atom *argv) +{ + t_atom *out; + + if (x->d_allsnd->s_thing) { + out = (t_atom*)getbytes(sizeof(t_atom)*(argc+2)); + memcpy(&out[2], argv, argc*sizeof(t_atom)); + SETFLOAT(&out[0],x->d_num); + SETSYMBOL(&out[1],s); + + typedmess(x->d_allsnd->s_thing, &s_list, argc+2, out); + + freebytes(out, sizeof(t_atom)*(argc+2)); + } +} + + + +/*--------------------- dispatch ------------------------------------*/ + +static void *dispatch_new(t_symbol *s,t_float from,t_float to) +{ + int i,len; + t_dispatch *x = (t_dispatch *)pd_new(dispatch_class); + char str[512]; + t_symbol *allsnd,*eachsnd; + + x->x_snds=0; + x->x_sym = s; + x->x_from = from; + x->x_to = to; + len=x->x_to-x->x_from+1; + + if(len>0){ + sprintf(str,"%s-snd",x->x_sym->s_name); + allsnd=gensym(str); + + sprintf(str,"%s-rcv",x->x_sym->s_name); + x->x_allrcv=gensym(str); + pd_bind((t_pd*)x, x->x_allrcv); + + x->x_snds=getbytes(len*sizeof(t_dispsnd *)); + x->x_eachrcvs=getbytes(len*sizeof(t_symbol *)); + + for(i=0;ix_sym->s_name,i+x->x_from); + eachsnd=gensym(str); + x->x_snds[i]=dispsnd_new(eachsnd,allsnd,i+x->x_from); + + sprintf(str,"%s%d-rcv",x->x_sym->s_name,i+x->x_from); + x->x_eachrcvs[i]=gensym(str); + } + } + return (x); +} + +static void dispatch_ff(t_dispatch *x) +{ + int i,len=x->x_to-x->x_from+1; + + if(len<=0) return; + + pd_unbind((t_pd*)x, x->x_allrcv); + + for(i=0;ix_snds[i]); + + freebytes(x->x_snds,len*sizeof(t_dispsnd *)); + freebytes(x->x_eachrcvs,len*sizeof(t_symbol *)); +} + + +static void dispatch_list(t_dispatch *x, t_symbol *s, int argc, t_atom *argv) +{ + int num; + + if((!argc)|(argv[0].a_type!=A_FLOAT)) { + error("dispatch: bad list format"); + return; + } + + num=atom_getint(&argv[0]); + + if((numx_from)|(num>x->x_to)) { + //error("dispatch: bad num"); + return; + } + + if (x->x_eachrcvs[num-x->x_from]->s_thing) + pd_forwardmess(x->x_eachrcvs[num-x->x_from]->s_thing, argc-1, argv+1); +} + + + + +/*--------------------------------------------------------------*/ + +void dispatch_setup(void) +{ + dispatch_class = class_new(gensym("dispatch"), (t_newmethod)dispatch_new, + (t_method)dispatch_ff, + sizeof(t_dispatch), 0, A_SYMBOL, A_FLOAT, A_FLOAT,0); + + class_addlist(dispatch_class, dispatch_list); + dispsnd_class = class_new(gensym("dispatch"), 0, (t_method)dispsnd_ff, + sizeof(t_dispsnd), CLASS_PD, 0); + class_addanything(dispsnd_class, dispsnd_anything); + class_addfloat(dispsnd_class, dispsnd_float); +} + diff --git a/dripchar.c b/dripchar.c new file mode 100644 index 0000000..184e204 --- /dev/null +++ b/dripchar.c @@ -0,0 +1,82 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/*#include */ +#include "m_pd.h" + +#include +#include +#include +#include + +typedef struct _dripchar +{ + t_object x_obj; +}t_dripchar; + +t_class *dripchar_class; + +void dripchar_setup(void); + +static void dripchar_symbol(t_dripchar *x,t_symbol *sym) +{ + static t_binbuf *binbuf=0; + t_atom at; + char *c,s[2]={0}; + int l; + + if(!binbuf) binbuf=binbuf_new(); + /*post("dripchar_symbol");*/ + if(!sym->s_name) return; + + c=sym->s_name; + while(*c) { + s[0]=*c++; + SETSYMBOL(&at,gensym(s)); + binbuf_add(binbuf,1,&at); + } + + + outlet_list(x->x_obj.ob_outlet,0, + binbuf_getnatom(binbuf),binbuf_getvec(binbuf)); + binbuf_clear(binbuf); +} + +static void dripchar_float(t_dripchar *x,t_floatarg f) +{ + post("dripchar_float"); + /*outlet_symbol(x->x_obj.ob_outlet,*/ +} + +static void *dripchar_new(void) +{ + t_dripchar *x = (t_dripchar *)pd_new(dripchar_class); + outlet_new(&x->x_obj, 0); + return (void *)x; +} + +void dripchar_setup(void) +{ + dripchar_class = class_new(gensym("dripchar"),(t_newmethod)dripchar_new, + 0, sizeof(t_dripchar), 0, 0); + + class_addsymbol(dripchar_class, dripchar_symbol); + class_addfloat(dripchar_class, dripchar_float); +} + diff --git a/f2char.c b/f2char.c new file mode 100644 index 0000000..e14c5cf --- /dev/null +++ b/f2char.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" + +typedef struct _f2char +{ + t_object x_obj; +}t_f2char; + +t_class *f2char_class; + +void f2char_setup(void); + +static void f2char_float(t_f2char *x,t_floatarg f) +{ + char s[2]={0}; + + s[0]=(char)f; + outlet_symbol(x->x_obj.ob_outlet,gensym(s)); +} + +static void *f2char_new(void) +{ + t_f2char *x = (t_f2char *)pd_new(f2char_class); + outlet_new(&x->x_obj,&s_symbol); + return (void *)x; +} + +void f2char_setup(void) +{ + f2char_class = class_new(gensym("f2char"),(t_newmethod)f2char_new, + 0, sizeof(t_f2char), 0, 0); + + class_addfloat(f2char_class, f2char_float); +} + diff --git a/gamme.c b/gamme.c new file mode 100644 index 0000000..d4ddd01 --- /dev/null +++ b/gamme.c @@ -0,0 +1,558 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ +#include +#include +#include +#include "g_canvas.h" + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ gamme ----------------------------- */ +#define BACKGROUND "-fill grey" +#define BACKGROUNDCOLOR "grey" + +#ifndef PD_VERSION_MINOR +#define PD_VERSION_MINOR 32 +#endif + +#define IS_A_POINTER(atom,index) ((atom+index)->a_type == A_POINTER) +#define IS_A_FLOAT(atom,index) ((atom+index)->a_type == A_FLOAT) +#define IS_A_SYMBOL(atom,index) ((atom+index)->a_type == A_SYMBOL) + + +#define DEFAULTSIZE 15 +#define DEFAULTWIDTH 90 +#define DEFAULTHEIGHT 40 + +#define DEFAULTCOLOR "black" +#define BLACKCOLOR "black" +#define WHITECOLOR "white" +#define SELBLACKCOLOR "gold" +#define SELWHITECOLOR "yellow" + + +static t_class *gamme_class; + +static char *NoteNames[]= + { "C","C#","D","D#","E","F","F#","G","G#","A","A#","B" }; +static char NoteColPos[]= + { 1,-1,2,-2,3,4,-4,5,-5,6,-6,7 }; +static char Whites[]={0,2,4,5,7,9,11}; +static char Blacks[]={1,3,6,8,10}; +static char BlacksWhites[]={1,3,6,8,10,0,2,4,5,7,9,11}; +static char WhitesBlacks[]={0,2,4,5,7,9,11,1,3,6,8,10}; + +#define ISWHITE(x) (NoteColPos[x]>0) +#define ISBLACK(x) (!ISWHITE(x)) + +#define te_xpos te_xpix +#define te_ypos te_ypix + +typedef struct _gamme +{ + t_object x_obj; + t_outlet *x_out_n; /*gives the number of selected notes when change occurs*/ + t_outlet *x_out_note; /*gives the number and new value of the changed notes when change occurs*/ + t_glist * x_glist; + int x_width; + int x_height; + char x_n; + char x_notes[12]; + char x_on_notes[12]; +} t_gamme; + +/* widget helper functions */ + + +#define INTERSPACE 0.02 +#define NOTEWIDTH ((1-INTERSPACE*6.0)/7.0) +#define BLACK1st ((NOTEWIDTH+INTERSPACE)/2.0) +#define BLACKH 0.6 +static void note_get_rel_rect(int x, float *xp1, float *yp1, float *xp2, float *yp2) +{ + int cp=NoteColPos[x]; + + *xp1=(abs(cp)-1)*(NOTEWIDTH+INTERSPACE) + (cp<0)*BLACK1st; + *xp2=*xp1+NOTEWIDTH; + + *yp1=0; + *yp2=cp<0?BLACKH:1; +} + +static int get_touched_note(float x, float y) +{ + int i,j; + float xp1,xp2,yp1,yp2; + + for(j=0;j<12;j++) { + i=BlacksWhites[j]; + note_get_rel_rect(i,&xp1,&yp1,&xp2,&yp2); + if((x>=xp1)&&(x<=xp2)&&(y>=yp1)&&(y<=yp2)) + return i; + } + /*post("gamme::get_touched_note note not found: x=%f y=%f",x,y);*/ + return -1; +} + +static void draw_inlets(t_gamme *x, t_glist *glist, int firsttime, int nin, int nout) +{ + int n = nout; + int nplus, i; + int xpos=text_xpix(&x->x_obj, glist); + int ypos=text_ypix(&x->x_obj, glist); + + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = xpos + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xo%d\n", + glist_getcanvas(glist), + onset, ypos + x->x_height - 1, + onset + IOWIDTH, ypos + x->x_height, + x, i); + else + sys_vgui(".x%x.c coords %xo%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, ypos + x->x_height - 1, + onset + IOWIDTH, ypos + x->x_height); + } + n = nin; + nplus = (n == 1 ? 1 : n-1); + for (i = 0; i < n; i++) + { + int onset = xpos + (x->x_width - IOWIDTH) * i / nplus; + if (firsttime) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xi%d\n", + glist_getcanvas(glist), + onset, ypos, + onset + IOWIDTH, ypos + 1, + x, i); + else + sys_vgui(".x%x.c coords %xi%d %d %d %d %d\n", + glist_getcanvas(glist), x, i, + onset, ypos, + onset + IOWIDTH, ypos + 1); + + } +} + +void gamme_drawme(t_gamme *x, t_glist *glist, int firsttime) +{ + int i,j; + float x1,y1,x2,y2; + int xi1,yi1,xi2,yi2; + char *color; + int xpos=text_xpix(&x->x_obj, glist); + int ypos=text_ypix(&x->x_obj, glist); + + if (firsttime) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xS "BACKGROUND"\n", + glist_getcanvas(glist), + xpos, ypos, + xpos + x->x_width, ypos + x->x_height, + x); + + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d %d %d\n", + glist_getcanvas(glist), x, + xpos, ypos, + xpos + x->x_width, ypos + x->x_height); + } + + for(j=0;j<12;j++){ + i=WhitesBlacks[j]; + note_get_rel_rect(i,&x1,&y1,&x2,&y2); + xi1=xpos + x->x_width*x1; + xi2=xpos + x->x_width*x2; + yi1=ypos + x->x_height*y1; + yi2=ypos + x->x_height*y2; + + if (firsttime) { + color=x->x_notes[i]? (ISWHITE(i)?SELWHITECOLOR:SELBLACKCOLOR): + (ISWHITE(i)?WHITECOLOR:BLACKCOLOR); + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %x%s -fill %s\n", + glist_getcanvas(glist),xi1,yi1,xi2,yi2, + x,NoteNames[i],color); + } + else { + sys_vgui(".x%x.c coords %x%s \ +%d %d %d %d\n", + glist_getcanvas(glist),x,NoteNames[i],xi1,yi1,xi2,yi2); + } + } + + draw_inlets(x, glist, firsttime, 1,3); + +} + +void gamme_erase(t_gamme* x,t_glist* glist) +{ + int n; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c delete %xS\n",canvas, x); + + for(n=0;n<12;n++) + sys_vgui(".x%x.c delete %x%s\n",canvas,x,NoteNames[n]); + + n = 1; + while (n--) { + sys_vgui(".x%x.c delete %xi%d\n",canvas,x,n); + } + n = 3; + while (n--) { + sys_vgui(".x%x.c delete %xo%d\n",canvas,x,n); + } +} + + + +/* ------------------------ gamme widgetbehaviour----------------------------- */ + + +static void gamme_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_gamme *x = (t_gamme *)z; + int width, height; + t_gamme* s = (t_gamme*)z; + + + width = s->x_width; + height = s->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = *xp1 + width; + *yp2 = *yp1 + height; +} + +static void gamme_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_gamme *x = (t_gamme *)z; + x->x_obj.te_xpos += dx; + x->x_obj.te_ypos += dy; + gamme_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void gamme_select(t_gobj *z, t_glist *glist, int state) +{ + t_gamme *x = (t_gamme *)z; + sys_vgui(".x%x.c itemconfigure %xS -fill %s\n", glist, + x, (state? "blue" : BACKGROUNDCOLOR)); +} + + +static void gamme_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void gamme_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + canvas_deletelinesfor(glist, x); +} + + +static void gamme_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_gamme* s = (t_gamme*)z; + if (vis) + gamme_drawme(s, glist, 1); + else + gamme_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void gamme_save(t_gobj *z, t_binbuf *b) +{ + t_gamme *x = (t_gamme *)z; + char *c=x->x_notes; + + binbuf_addv(b, "ssiisiiiiiiiiiiiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_obj.te_xpos, (t_int)x->x_obj.te_ypos, + gensym("gamme"),x->x_width,x->x_height, + c[0],c[1],c[2],c[3],c[4],c[5],c[6],c[7],c[8],c[9],c[10],c[11]); + binbuf_addv(b, ";"); +} + +void gamme_getn(t_gamme *x) +{ + outlet_float(x->x_out_n,x->x_n); +} + +void gamme_out_changed(t_gamme *x,int note) +{ + t_atom ats[2]; + SETFLOAT(&ats[0],note); + SETFLOAT(&ats[1],x->x_notes[note]); + + outlet_list(x->x_out_note,0,2,ats); +} + +inline float my_mod(float x,int n) +{ + float y=fmod(x,n); + return y<0?y+n:y; +} + +#define my_div(x,y) (floor(x/y)) +#define tonotei(x) (my_mod(rint(x),12U)) + +void gamme_set(t_gamme *x,t_floatarg note,t_floatarg on) +{ + unsigned int i,notei=tonotei(note),changed=0; + char *color; + t_canvas *canvas=glist_getcanvas(x->x_glist); + + + if(x->x_notes[notei]!=on) changed=1; + if(on<0) x->x_notes[notei]=!(x->x_notes[notei]); + else x->x_notes[notei]=on; + if(changed) gamme_out_changed(x,notei); + + color=x->x_notes[notei]?(ISWHITE(notei)?SELWHITECOLOR:SELBLACKCOLOR): + (ISWHITE(notei)?WHITECOLOR:BLACKCOLOR); + + if(glist_isvisible(x->x_glist)) + sys_vgui(".x%x.c itemconfigure %x%s -fill %s\n", canvas, + x, NoteNames[notei],color); + + x->x_n=0; + for(i=0;i<12;i++) if(x->x_notes[i]) x->x_on_notes[(int)(x->x_n++)]=i; + gamme_getn(x); +} + +#define getnote(n) \ + (my_div(n,(int)x->x_n)*12+x->x_on_notes[(int)my_mod(n,x->x_n)]) +void gamme_get(t_gamme *x,t_floatarg ref_octave,t_floatarg note) +{ + int no0,no1,ni0,ni1,n0,n1,n; + float xn,xx,nn; + + if(!x->x_n) return; + no0=floor(note); + no1=ceil(note); + xx=note-no0; + + nn=getnote((float)no0)*(1-xx)+getnote((float)(no0+1))*xx+ref_octave*12; + n=getnote((float)no0)+ref_octave*12; + outlet_float(x->x_obj.ob_outlet,nn); +} + +static void gamme_click(t_gamme *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + int note; + int x0=text_xpix(&x->x_obj, x->x_glist); + int y0=text_ypix(&x->x_obj, x->x_glist); + + note=get_touched_note( + (xpos-x0)/x->x_width, + (ypos-y0)/x->x_height); + + if(note>=0) gamme_set(x,note,!x->x_notes[note]); +} + +static int gamme_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_gamme* x = (t_gamme *)z; + + if(doit) + { + gamme_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + } + return (1); +} + +void gamme_float(t_gamme *x,t_floatarg f) +{ + unsigned int notei=tonotei(f); + + /*post("notei=%d",notei);*/ + if(x->x_notes[notei]) + outlet_float(x->x_obj.ob_outlet,f); +} + +void gamme_round(t_gamme *x,t_floatarg f,t_floatarg round) +{ + unsigned int notei=tonotei(f); + int imin=floor(f),imax=ceil(f); + float norm; + + if(!x->x_n) return; + + while(!x->x_notes[(int)my_mod((imin),12U)]) imin--; + while(!x->x_notes[(int)my_mod((imax),12U)]) imax++; + + /*post("min: %d max: %d",imin,imax);*/ + + if((imin!=imax)&&round) { + round*=round; + norm=(f-imin)/(imax-imin)*2-1; + norm=norm/sqrt(1+round*norm*norm)*sqrt(1+round)/2+.5; + f=norm*(imax-imin)+imin; + } + outlet_float(x->x_obj.ob_outlet,f); +} + +void gamme_setall(t_gamme *x,t_symbol *s, int argc, t_atom *argv) +{ + int i=0,err=0; + + if(argc==12) + { + for(i=0;i<12;i++) err+=!IS_A_FLOAT(argv,i); + if(!err) for(i=0;i<12;i++) gamme_set(x,i,atom_getfloat(&argv[i])); + } +} + +void gamme_getall(t_gamme *x) +{ + int i=0; + + for(i=0;i<12;i++) gamme_out_changed(x,i); + gamme_getn(x); +} + +extern int sys_noloadbang; +static void gamme_loadbang(t_gamme *x) +{ + int i; + + if(sys_noloadbang) return; + for(i=0;i<12;i++) gamme_out_changed(x,i); + gamme_getn(x); +} + +void gamme_size(t_gamme* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; + gamme_drawme(x, x->x_glist, 0); +} + +t_widgetbehavior gamme_widgetbehavior; + +static void gamme_setwidget(void) +{ + gamme_widgetbehavior.w_getrectfn = gamme_getrect; + gamme_widgetbehavior.w_displacefn = gamme_displace; + gamme_widgetbehavior.w_selectfn = gamme_select; + gamme_widgetbehavior.w_activatefn = gamme_activate; + gamme_widgetbehavior.w_deletefn = gamme_delete; + gamme_widgetbehavior.w_visfn = gamme_vis; + gamme_widgetbehavior.w_clickfn = gamme_newclick; + //gamme_widgetbehavior.w_propertiesfn = NULL; + //gamme_widgetbehavior.w_savefn = gamme_save; +} + + +static void *gamme_new(t_symbol *s, int argc, t_atom *argv) +{ + int i=0,err=0; + + t_gamme *x = (t_gamme *)pd_new(gamme_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + x->x_width = DEFAULTWIDTH; + x->x_height = DEFAULTHEIGHT; + outlet_new(&x->x_obj, &s_float); + x->x_out_n=outlet_new(&x->x_obj, &s_float); + x->x_out_note=outlet_new(&x->x_obj, &s_float); + + x->x_n=0; + for(i=0;i<12;i++) x->x_notes[i]=0; + for(i=0;i<12;i++) x->x_on_notes[i]=0; + + if((argc>1)&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1)) + { + if(atom_getfloat(&argv[0])) x->x_width = atom_getfloat(&argv[0]); + if(atom_getfloat(&argv[1])) x->x_height = atom_getfloat(&argv[1]); + + if(argc==14) + { + for(i=0;i<12;i++) err+=(!IS_A_FLOAT(argv,i+2)); + if(!err) { + for(i=0;i<12;i++) if(x->x_notes[i]=atom_getfloat(&argv[i+2])) + x->x_on_notes[(int)(x->x_n++)]=i; + /*gamme_set(x,i,atom_getfloat(&argv[i+2]));gamme_getn(x);*/ + } + else post("gamme_new : error in creation arguments"); + } + /*if(argc==14) gamme_setall(x,s,argc-2,&argv[2]);*/ + } + + return (x); +} + +void gamme_setup(void) +{ + post("gamme_setup"); + gamme_class = class_new(gensym("gamme"), (t_newmethod)gamme_new, 0, + sizeof(t_gamme),0, A_GIMME,0); + + class_addfloat(gamme_class,gamme_float); + + class_addmethod(gamme_class, (t_method)gamme_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_set, gensym("set"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_get, gensym("get"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_round, gensym("round"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(gamme_class, (t_method)gamme_setall, gensym("setall"), + A_GIMME, 0); + + class_addmethod(gamme_class, (t_method)gamme_getall, gensym("getall"), 0); + + class_addmethod(gamme_class, (t_method)gamme_getn, gensym("getn"), 0); + + /*class_addmethod(gamme_class, (t_method)gamme_loadbang, gensym("loadbang"), 0);*/ + + + gamme_setwidget(); + class_setwidget(gamme_class,&gamme_widgetbehavior); + class_setsavefn(gamme_class, gamme_save); + +} + + diff --git a/help/absolutepath-help.pd b/help/absolutepath-help.pd new file mode 100644 index 0000000..b056f4a --- /dev/null +++ b/help/absolutepath-help.pd @@ -0,0 +1,13 @@ +#N canvas 14 323 660 379 10; +#X text 17 352 (c) Antoine Rousseau 2004; +#X obj 33 108 absolutepath; +#X symbolatom 33 131 0 0 0; +#X msg 33 51 symbol absolutepath.pd; +#X obj 33 220 relativepath; +#X symbolatom 33 245 0 0 0; +#X text 14 6 absolutepath / relativepath : use filenames relatively +to the patch's path.; +#X connect 1 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 1 0; +#X connect 4 0 5 0; diff --git a/help/basedir-help.pd b/help/basedir-help.pd new file mode 100644 index 0000000..cbf9c9e --- /dev/null +++ b/help/basedir-help.pd @@ -0,0 +1,18 @@ +#N canvas 136 196 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty basedir 20 20 1 18 -262144 -1109 +0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 135 12 basename/dirname functions; +#X obj 124 102 basedir; +#X obj 124 136 unpack s s; +#X symbolatom 124 158 0 0 0; +#X symbolatom 189 158 0 0 0; +#X msg 124 62 symbol /usr/local/bin/pd; +#X obj 124 42 loadbang; +#X text 108 175 basename; +#X text 212 175 dirname; +#X connect 3 0 4 0; +#X connect 4 0 5 0; +#X connect 4 1 6 0; +#X connect 7 0 3 0; +#X connect 8 0 7 0; diff --git a/help/char2f-help.pd b/help/char2f-help.pd new file mode 100644 index 0000000..f133288 --- /dev/null +++ b/help/char2f-help.pd @@ -0,0 +1,18 @@ +#N canvas 134 318 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty char2f_f2char 10 20 1 18 -262144 +-1109 0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 160 14 ascii utilities; +#X obj 131 115 char2f; +#X floatatom 131 136 5 0 0; +#X msg 131 69 symbol A; +#X obj 131 173 f2char; +#X symbolatom 131 194 2 0 0; +#X obj 131 49 loadbang; +#X msg 216 70 symbol a; +#X connect 3 0 4 0; +#X connect 4 0 6 0; +#X connect 5 0 3 0; +#X connect 6 0 7 0; +#X connect 8 0 5 0; +#X connect 9 0 3 0; diff --git a/help/comma-help.pd b/help/comma-help.pd new file mode 100644 index 0000000..b8a8e63 --- /dev/null +++ b/help/comma-help.pd @@ -0,0 +1,40 @@ +#N canvas 172 316 715 428 10; +#X obj 0 0 cnv 8 100 60 empty empty comma 10 20 1 18 -262144 -1109 +0; +#X text 109 12 how to write " \, " in a message...; +#X text 2 388 (c) Moonix: Antoine Rousseau 2004; +#X msg 71 101 foo 1 \, bar 2; +#X floatatom 70 340 5 0 0 0 - - -; +#X floatatom 113 341 5 0 0 0 - - -; +#X obj 70 318 route foo bar; +#X text 59 85 build a message like this:; +#X text 106 118 | notice the comma...; +#X text 106 116 ^; +#X obj 437 192 drip; +#X obj 396 192 comma; +#X msg 417 222 add2 \$1; +#X msg 372 110 foo 10; +#X obj 407 171 t b a; +#X msg 331 82 set; +#X msg 427 110 bar 20; +#X msg 417 249 foo 10 \, bar 20 \,; +#X obj 517 171 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X text 39 72 0: what we want to do is to; +#X text 299 64 1: reset the message; +#X text 375 92 2: add parts; +#X text 467 153 (or click the message directly); +#X text 453 142 3: send the message; +#X connect 3 0 6 0; +#X connect 6 0 4 0; +#X connect 6 1 5 0; +#X connect 10 0 12 0; +#X connect 11 0 12 0; +#X connect 12 0 17 0; +#X connect 13 0 14 0; +#X connect 14 0 11 0; +#X connect 14 1 10 0; +#X connect 15 0 17 0; +#X connect 16 0 14 0; +#X connect 17 0 6 0; +#X connect 18 0 17 0; diff --git a/help/d/d0.gif b/help/d/d0.gif new file mode 100644 index 0000000..89fd454 Binary files /dev/null and b/help/d/d0.gif differ diff --git a/help/d/d1.gif b/help/d/d1.gif new file mode 100644 index 0000000..3bdd5b6 Binary files /dev/null and b/help/d/d1.gif differ diff --git a/help/d/d10.gif b/help/d/d10.gif new file mode 100644 index 0000000..13941b5 Binary files /dev/null and b/help/d/d10.gif differ diff --git a/help/d/d11.gif b/help/d/d11.gif new file mode 100644 index 0000000..05489a9 Binary files /dev/null and b/help/d/d11.gif differ diff --git a/help/d/d12.gif b/help/d/d12.gif new file mode 100644 index 0000000..b6f2e79 Binary files /dev/null and b/help/d/d12.gif differ diff --git a/help/d/d13.gif b/help/d/d13.gif new file mode 100644 index 0000000..95ac806 Binary files /dev/null and b/help/d/d13.gif differ diff --git a/help/d/d14.gif b/help/d/d14.gif new file mode 100644 index 0000000..c820bcb Binary files /dev/null and b/help/d/d14.gif differ diff --git a/help/d/d15.gif b/help/d/d15.gif new file mode 100644 index 0000000..aadd006 Binary files /dev/null and b/help/d/d15.gif differ diff --git a/help/d/d16.gif b/help/d/d16.gif new file mode 100644 index 0000000..b6b7429 Binary files /dev/null and b/help/d/d16.gif differ diff --git a/help/d/d17.gif b/help/d/d17.gif new file mode 100644 index 0000000..dbc581a Binary files /dev/null and b/help/d/d17.gif differ diff --git a/help/d/d18.gif b/help/d/d18.gif new file mode 100644 index 0000000..d2699d0 Binary files /dev/null and b/help/d/d18.gif differ diff --git a/help/d/d19.gif b/help/d/d19.gif new file mode 100644 index 0000000..082ad9a Binary files /dev/null and b/help/d/d19.gif differ diff --git a/help/d/d2.gif b/help/d/d2.gif new file mode 100644 index 0000000..c1cd34f Binary files /dev/null and b/help/d/d2.gif differ diff --git a/help/d/d20.gif b/help/d/d20.gif new file mode 100644 index 0000000..2bf3398 Binary files /dev/null and b/help/d/d20.gif differ diff --git a/help/d/d21.gif b/help/d/d21.gif new file mode 100644 index 0000000..e1b9463 Binary files /dev/null and b/help/d/d21.gif differ diff --git a/help/d/d22.gif b/help/d/d22.gif new file mode 100644 index 0000000..b33a110 Binary files /dev/null and b/help/d/d22.gif differ diff --git a/help/d/d23.gif b/help/d/d23.gif new file mode 100644 index 0000000..cef38bf Binary files /dev/null and b/help/d/d23.gif differ diff --git a/help/d/d24.gif b/help/d/d24.gif new file mode 100644 index 0000000..629442d Binary files /dev/null and b/help/d/d24.gif differ diff --git a/help/d/d25.gif b/help/d/d25.gif new file mode 100644 index 0000000..87b766a Binary files /dev/null and b/help/d/d25.gif differ diff --git a/help/d/d26.gif b/help/d/d26.gif new file mode 100644 index 0000000..3a45164 Binary files /dev/null and b/help/d/d26.gif differ diff --git a/help/d/d27.gif b/help/d/d27.gif new file mode 100644 index 0000000..257f589 Binary files /dev/null and b/help/d/d27.gif differ diff --git a/help/d/d28.gif b/help/d/d28.gif new file mode 100644 index 0000000..0de8ba8 Binary files /dev/null and b/help/d/d28.gif differ diff --git a/help/d/d29.gif b/help/d/d29.gif new file mode 100644 index 0000000..588f65c Binary files /dev/null and b/help/d/d29.gif differ diff --git a/help/d/d3.gif b/help/d/d3.gif new file mode 100644 index 0000000..1d6528b Binary files /dev/null and b/help/d/d3.gif differ diff --git a/help/d/d30.gif b/help/d/d30.gif new file mode 100644 index 0000000..1962cb8 Binary files /dev/null and b/help/d/d30.gif differ diff --git a/help/d/d31.gif b/help/d/d31.gif new file mode 100644 index 0000000..4b5dd54 Binary files /dev/null and b/help/d/d31.gif differ diff --git a/help/d/d32.gif b/help/d/d32.gif new file mode 100644 index 0000000..37391dc Binary files /dev/null and b/help/d/d32.gif differ diff --git a/help/d/d33.gif b/help/d/d33.gif new file mode 100644 index 0000000..5ce47b2 Binary files /dev/null and b/help/d/d33.gif differ diff --git a/help/d/d34.gif b/help/d/d34.gif new file mode 100644 index 0000000..29f5804 Binary files /dev/null and b/help/d/d34.gif differ diff --git a/help/d/d35.gif b/help/d/d35.gif new file mode 100644 index 0000000..0f2ac0f Binary files /dev/null and b/help/d/d35.gif differ diff --git a/help/d/d36.gif b/help/d/d36.gif new file mode 100644 index 0000000..2c59cf6 Binary files /dev/null and b/help/d/d36.gif differ diff --git a/help/d/d37.gif b/help/d/d37.gif new file mode 100644 index 0000000..290e514 Binary files /dev/null and b/help/d/d37.gif differ diff --git a/help/d/d38.gif b/help/d/d38.gif new file mode 100644 index 0000000..246422c Binary files /dev/null and b/help/d/d38.gif differ diff --git a/help/d/d39.gif b/help/d/d39.gif new file mode 100644 index 0000000..c09316e Binary files /dev/null and b/help/d/d39.gif differ diff --git a/help/d/d4.gif b/help/d/d4.gif new file mode 100644 index 0000000..16c157c Binary files /dev/null and b/help/d/d4.gif differ diff --git a/help/d/d40.gif b/help/d/d40.gif new file mode 100644 index 0000000..15a4f98 Binary files /dev/null and b/help/d/d40.gif differ diff --git a/help/d/d41.gif b/help/d/d41.gif new file mode 100644 index 0000000..a618a8a Binary files /dev/null and b/help/d/d41.gif differ diff --git a/help/d/d42.gif b/help/d/d42.gif new file mode 100644 index 0000000..0a2f7ab Binary files /dev/null and b/help/d/d42.gif differ diff --git a/help/d/d43.gif b/help/d/d43.gif new file mode 100644 index 0000000..9a52db3 Binary files /dev/null and b/help/d/d43.gif differ diff --git a/help/d/d44.gif b/help/d/d44.gif new file mode 100644 index 0000000..b649b7c Binary files /dev/null and b/help/d/d44.gif differ diff --git a/help/d/d45.gif b/help/d/d45.gif new file mode 100644 index 0000000..6926b51 Binary files /dev/null and b/help/d/d45.gif differ diff --git a/help/d/d46.gif b/help/d/d46.gif new file mode 100644 index 0000000..ef6966c Binary files /dev/null and b/help/d/d46.gif differ diff --git a/help/d/d47.gif b/help/d/d47.gif new file mode 100644 index 0000000..f22a248 Binary files /dev/null and b/help/d/d47.gif differ diff --git a/help/d/d48.gif b/help/d/d48.gif new file mode 100644 index 0000000..b76e2e2 Binary files /dev/null and b/help/d/d48.gif differ diff --git a/help/d/d49.gif b/help/d/d49.gif new file mode 100644 index 0000000..4db26a3 Binary files /dev/null and b/help/d/d49.gif differ diff --git a/help/d/d5.gif b/help/d/d5.gif new file mode 100644 index 0000000..5245f49 Binary files /dev/null and b/help/d/d5.gif differ diff --git a/help/d/d50.gif b/help/d/d50.gif new file mode 100644 index 0000000..acae768 Binary files /dev/null and b/help/d/d50.gif differ diff --git a/help/d/d51.gif b/help/d/d51.gif new file mode 100644 index 0000000..345177e Binary files /dev/null and b/help/d/d51.gif differ diff --git a/help/d/d52.gif b/help/d/d52.gif new file mode 100644 index 0000000..371ee22 Binary files /dev/null and b/help/d/d52.gif differ diff --git a/help/d/d53.gif b/help/d/d53.gif new file mode 100644 index 0000000..0aaeed8 Binary files /dev/null and b/help/d/d53.gif differ diff --git a/help/d/d54.gif b/help/d/d54.gif new file mode 100644 index 0000000..4eae9e5 Binary files /dev/null and b/help/d/d54.gif differ diff --git a/help/d/d55.gif b/help/d/d55.gif new file mode 100644 index 0000000..f7579f0 Binary files /dev/null and b/help/d/d55.gif differ diff --git a/help/d/d56.gif b/help/d/d56.gif new file mode 100644 index 0000000..56157aa Binary files /dev/null and b/help/d/d56.gif differ diff --git a/help/d/d57.gif b/help/d/d57.gif new file mode 100644 index 0000000..eba1418 Binary files /dev/null and b/help/d/d57.gif differ diff --git a/help/d/d58.gif b/help/d/d58.gif new file mode 100644 index 0000000..9952fb4 Binary files /dev/null and b/help/d/d58.gif differ diff --git a/help/d/d59.gif b/help/d/d59.gif new file mode 100644 index 0000000..ec69b2c Binary files /dev/null and b/help/d/d59.gif differ diff --git a/help/d/d6.gif b/help/d/d6.gif new file mode 100644 index 0000000..fd27e6d Binary files /dev/null and b/help/d/d6.gif differ diff --git a/help/d/d60.gif b/help/d/d60.gif new file mode 100644 index 0000000..8cfd531 Binary files /dev/null and b/help/d/d60.gif differ diff --git a/help/d/d61.gif b/help/d/d61.gif new file mode 100644 index 0000000..937089a Binary files /dev/null and b/help/d/d61.gif differ diff --git a/help/d/d62.gif b/help/d/d62.gif new file mode 100644 index 0000000..1ac6be2 Binary files /dev/null and b/help/d/d62.gif differ diff --git a/help/d/d63.gif b/help/d/d63.gif new file mode 100644 index 0000000..3642bb1 Binary files /dev/null and b/help/d/d63.gif differ diff --git a/help/d/d7.gif b/help/d/d7.gif new file mode 100644 index 0000000..dd74b47 Binary files /dev/null and b/help/d/d7.gif differ diff --git a/help/d/d8.gif b/help/d/d8.gif new file mode 100644 index 0000000..59251c0 Binary files /dev/null and b/help/d/d8.gif differ diff --git a/help/d/d9.gif b/help/d/d9.gif new file mode 100644 index 0000000..782e7b9 Binary files /dev/null and b/help/d/d9.gif differ diff --git a/help/dinlet~-help.pd b/help/dinlet~-help.pd new file mode 100644 index 0000000..8033afe --- /dev/null +++ b/help/dinlet~-help.pd @@ -0,0 +1,37 @@ +#N canvas 196 161 422 282 10; +#X text 6 248 (c) Antoine Rousseau 2001; +#X obj 9 5 dinlet~; +#X text 66 6 A signal inlet with a default value.; +#N canvas 178 154 300 161 --- 0; +#X obj 108 70 unsig~ 50; +#X obj 108 96 outlet; +#X obj 196 71 unsig~ 50; +#X obj 196 97 outlet; +#X obj 108 43 dinlet~ 1; +#X obj 196 44 dinlet~ 2; +#X obj 29 70 unsig~ 50; +#X obj 29 96 outlet; +#X obj 29 43 inlet~; +#X connect 0 0 1 0; +#X connect 2 0 3 0; +#X connect 4 0 0 0; +#X connect 5 0 2 0; +#X connect 6 0 7 0; +#X connect 8 0 6 0; +#X restore 112 100 pd ---; +#X floatatom 130 158 5 0 0; +#X floatatom 33 159 5 0 0; +#X floatatom 242 157 5 0 0; +#X obj 129 56 sig~ 5; +#X text 3 180 normal inlet~; +#X text 129 177 dinlet~ with; +#X text 128 192 default 1; +#X text 242 177 dinlet~ with; +#X text 241 192 default 2; +#X text 199 61 try connect and deconnect; +#X text 198 77 sig~ object to each of; +#X text 198 93 the subpatch inlets.; +#X connect 3 0 5 0; +#X connect 3 1 4 0; +#X connect 3 2 6 0; +#X connect 7 0 3 2; diff --git a/help/dispatch-help.pd b/help/dispatch-help.pd new file mode 100644 index 0000000..16231ef --- /dev/null +++ b/help/dispatch-help.pd @@ -0,0 +1,65 @@ +#N canvas 479 347 565 404 10; +#X obj 0 0 cnv 8 100 60 empty empty dispatch 10 20 1 18 -262144 -1109 +0; +#X obj 40 131 r foo1-rcv; +#X obj 40 151 print foo1; +#X obj 121 131 r foo2-rcv; +#X obj 121 151 print foo2; +#X obj 198 132 r foo3-rcv; +#X obj 198 152 print foo3; +#X obj 293 78 dispatch foo 1 3; +#X text 291 60 args: name min-index max-index; +#X msg 310 102 2 truc; +#X text 132 12 link several pairs of send/receive addresses to; +#X msg 39 82 f1snd; +#X msg 119 83 f2snd; +#X msg 197 83 f3snd; +#X obj 39 102 s foo1-snd; +#X obj 119 103 s foo2-snd; +#X obj 197 103 s foo3-snd; +#X obj 310 154 r foo-snd; +#X obj 310 122 s foo-rcv; +#X obj 310 175 print foo-snd; +#X text 406 162 one "send" from all; +#X text 382 110 one "receive" to all; +#X obj 35 208 cnv 15 300 150 empty empty empty 20 12 0 14 -261681 -66577 +0; +#X obj 77 223 tgl 15 0 \$0-bar1-snd \$0-bar1-rcv bar1 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 104 223 tgl 15 0 \$0-bar2-snd \$0-bar2-rcv bar2 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 132 223 tgl 15 0 \$0-bar3-snd \$0-bar3-rcv bar3 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 49 223 tgl 15 0 \$0-bar0-snd \$0-bar0-rcv bar0 0 -6 1 8 -262144 +-1 -1 0 1; +#X obj 173 321 s \$0-bar-rcv; +#X obj 49 276 r \$0-bar-snd; +#X obj 173 276 hdl 15 0 0 4 empty empty empty 0 -6 0 8 -262144 -1 -1 +1; +#X obj 185 221 dispatch \$0-bar 0 3; +#X msg 173 297 \$1 bang; +#X obj 49 298 unpack f f; +#X floatatom 49 319 2 0 0 0 - - -; +#X floatatom 114 320 2 0 0 0 - - -; +#X text 5 383 (c) Moonix: Antoine Rousseau 2004; +#X text 362 238 Warning: you HAVE to name; +#X text 343 254 your boutton buses like this:; +#X text 362 241 _______; +#X text 351 280 (notice the -snd and -rcv); +#X text 351 268 skeletonX-snd skeletonX-rcv; +#X text 134 24 a single one \, in which datas are prepended by the +number; +#X text 134 37 of the receiver/sender.; +#X connect 1 0 2 0; +#X connect 3 0 4 0; +#X connect 5 0 6 0; +#X connect 9 0 18 0; +#X connect 11 0 14 0; +#X connect 12 0 15 0; +#X connect 13 0 16 0; +#X connect 17 0 19 0; +#X connect 28 0 32 0; +#X connect 29 0 31 0; +#X connect 31 0 27 0; +#X connect 32 0 33 0; +#X connect 32 1 34 0; diff --git a/help/dripchar-help.pd b/help/dripchar-help.pd new file mode 100644 index 0000000..6318f36 --- /dev/null +++ b/help/dripchar-help.pd @@ -0,0 +1,28 @@ +#N canvas 117 153 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty dripchar 10 20 1 18 -262144 -1109 +0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X obj 131 49 loadbang; +#X obj 131 95 dripchar; +#X msg 131 69 symbol Antoine; +#X text 132 12 drip characters from a symbol to a list; +#X obj 131 117 unpack s s s s s s s; +#X symbolatom 131 142 1 0 0; +#X symbolatom 153 142 1 0 0; +#X symbolatom 176 142 1 0 0; +#X symbolatom 198 142 1 0 0; +#X symbolatom 221 142 1 0 0; +#X symbolatom 243 142 1 0 0; +#X symbolatom 266 142 1 0 0; +#X msg 245 69 symbol moonix_; +#X connect 2 0 4 0; +#X connect 3 0 6 0; +#X connect 4 0 3 0; +#X connect 6 0 7 0; +#X connect 6 1 8 0; +#X connect 6 2 9 0; +#X connect 6 3 10 0; +#X connect 6 4 11 0; +#X connect 6 5 12 0; +#X connect 6 6 13 0; +#X connect 14 0 3 0; diff --git a/help/f2char-help.pd b/help/f2char-help.pd new file mode 100644 index 0000000..f133288 --- /dev/null +++ b/help/f2char-help.pd @@ -0,0 +1,18 @@ +#N canvas 134 318 430 247 10; +#X obj 0 0 cnv 8 100 60 empty empty char2f_f2char 10 20 1 18 -262144 +-1109 0; +#X text 7 221 (c) Moonix: Antoine Rousseau 2003; +#X text 160 14 ascii utilities; +#X obj 131 115 char2f; +#X floatatom 131 136 5 0 0; +#X msg 131 69 symbol A; +#X obj 131 173 f2char; +#X symbolatom 131 194 2 0 0; +#X obj 131 49 loadbang; +#X msg 216 70 symbol a; +#X connect 3 0 4 0; +#X connect 4 0 6 0; +#X connect 5 0 3 0; +#X connect 6 0 7 0; +#X connect 8 0 5 0; +#X connect 9 0 3 0; diff --git a/help/f2s-help.pd b/help/f2s-help.pd new file mode 100644 index 0000000..005754a --- /dev/null +++ b/help/f2s-help.pd @@ -0,0 +1,17 @@ +#N canvas -5 264 527 298 10; +#X text 27 268 (c) Antoine Rousseau 2001; +#X obj 44 31 f2s; +#X text 80 32 A float-to-symbol converter \, with scientific-mode writing. +; +#X floatatom 196 85 5 0 300; +#X obj 163 136 f2s; +#X obj 196 106 dbtorms; +#X symbolatom 163 158 4 0 0; +#X floatatom 207 158 0 0 0; +#X text 244 85 Touch this; +#X text 57 196 The idea: many decades in an always 4 characters long +symbol...; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 5 0 4 0; +#X connect 5 0 7 0; diff --git a/help/gamme-help.pd b/help/gamme-help.pd new file mode 100644 index 0000000..8f87eb0 --- /dev/null +++ b/help/gamme-help.pd @@ -0,0 +1,171 @@ +#N canvas 246 348 520 515 10; +#X text 10 491 (c) Antoine Rousseau 2001; +#X text 85 3 gamme: a musical scale selector.; +#X obj 113 187 gamme 90 40 1 0 0 0 1 0 0 1 0 0 0 0; +#X floatatom 51 244 6 0 0 0 - - -; +#X floatatom 134 71 4 0 0 0 - - -; +#X floatatom 33 78 4 0 0 0 - - -; +#X floatatom 154 244 4 0 0 0 - - -; +#X msg 280 256 set \$1 \$2; +#X obj 280 288 gamme 90 40 1 0 0 0 1 0 0 1 0 0 0 0; +#X msg 401 177 getall; +#X floatatom 322 336 4 0 0 0 - - -; +#X floatatom 282 72 6 0 0 0 - - -; +#X msg 282 138 round \$1 \$2; +#X obj 282 116 pack f f; +#X floatatom 363 71 4 0 200 0 - - -; +#X obj 281 227 print changed; +#X obj 134 119 pack f f; +#X floatatom 190 71 4 0 0 0 - - -; +#X obj 156 99 t b f; +#X msg 134 141 get \$1 \$2; +#X text 126 53 octave; +#X text 188 53 note; +#X text 271 56 semitone; +#X text 344 55 rounding strength; +#X obj 303 93 t b f; +#X text 19 59 semitone; +#X text 152 33 ARPEGE; +#X text 28 39 FILTER; +#X text 324 36 ROUNDING; +#X text 51 263 Result; +#X text 139 261 Number of; +#X text 127 273 selected notes; +#X text 377 238 in the key set.; +#X text 383 225 Last change; +#X text 371 158 get all the key set.; +#N canvas 483 118 375 520 audio 0; +#X obj 4 356 gamme 90 40 1 0 1 0 1 0 0 1 0 1 0 0; +#X obj 28 464 *~; +#X obj 4 419 mtof; +#X obj 4 442 osc~; +#N canvas 394 93 600 400 env 0; +#X obj 19 122 inlet; +#X obj 105 121 inlet; +#X msg 19 143 bang; +#X obj 89 280 line~; +#X obj 114 329 outlet~; +#X obj 114 307 *~; +#X obj 130 280 +~ 1; +#X obj 130 258 *~ 0.6; +#X obj 130 237 osc~ 12; +#X msg 89 228 0 \$1; +#X obj 89 206 200; +#X obj 48 206 0.2; +#X obj 64 121 inlet; +#X text 18 101 trig; +#X text 62 101 vol; +#X text 103 102 sustain; +#X text 133 219 lfo...; +#X msg 48 228 \$1 2; +#X obj 89 183 delay 2; +#X connect 0 0 2 0; +#X connect 1 0 10 1; +#X connect 2 0 11 0; +#X connect 2 0 18 0; +#X connect 3 0 5 0; +#X connect 5 0 4 0; +#X connect 6 0 5 1; +#X connect 7 0 6 0; +#X connect 8 0 7 0; +#X connect 9 0 3 0; +#X connect 10 0 9 0; +#X connect 11 0 17 0; +#X connect 12 0 11 1; +#X connect 17 0 3 0; +#X connect 18 0 10 0; +#X restore 44 441 pd env; +#X floatatom 51 236 5 0 0 0 - - -; +#X obj 17 499 dac~; +#X obj 62 421 pow 4; +#X obj 4 189 metro 180; +#X obj 4 211 i; +#X obj 4 162 tgl 20 0 empty empty play 0 -8 1 10 -262144 -1 -1 1 1 +; +#X obj 29 211 + 1; +#X obj 4 286 spigot; +#X obj 49 286 == 0; +#X obj 54 211 mod 16; +#X obj 91 287 spigot; +#X obj 136 287 == 1; +#X msg 91 309 get 4 \$1; +#X obj 233 251 unpack f; +#X obj 188 279 spigot; +#X msg 188 345 round \$1 \$2; +#X obj 188 323 pack f f; +#X obj 233 279 == 2; +#X obj 4 306 + 60; +#X obj 188 301 + 60.05; +#X obj 191 375 hsl 50 10 0 500 0 1 empty empty Sustain -2 -6 1 10 -262144 +-1 -1 1700 1; +#X obj 52 165 hsl 50 10 5 500 0 1 empty empty Metro(ms) -2 -6 1 10 +-262144 -1 -1 1200 1; +#X obj 318 165 vsl 10 40 0 100 0 1 empty empty Round 0 -8 1 10 -262144 +-1 -1 600 1; +#X obj 191 486 hsl 60 15 0 1 0 1 empty empty Volume -2 -6 1 10 -258699 +-1 -1 4300 1; +#X obj 149 88 cnv 15 90 47 empty empty filter/arpeg/round 2 8 1 10 +-233017 -1 0; +#X obj 149 162 hdl 30 0 1 3 empty empty empty 20 8 0 8 -262144 -1 -1 +0; +#X obj 13 328 inlet; +#X connect 0 0 4 0; +#X connect 0 0 2 0; +#X connect 1 0 6 0; +#X connect 1 0 6 1; +#X connect 2 0 3 0; +#X connect 3 0 1 0; +#X connect 4 0 1 1; +#X connect 5 0 15 0; +#X connect 5 0 12 0; +#X connect 5 0 19 0; +#X connect 7 0 4 1; +#X connect 8 0 9 0; +#X connect 9 0 5 0; +#X connect 9 0 11 0; +#X connect 10 0 8 0; +#X connect 11 0 14 0; +#X connect 12 0 23 0; +#X connect 13 0 12 1; +#X connect 14 0 9 1; +#X connect 15 0 17 0; +#X connect 16 0 15 1; +#X connect 17 0 0 0; +#X connect 18 0 16 0; +#X connect 18 0 22 0; +#X connect 18 0 13 0; +#X connect 19 0 24 0; +#X connect 20 0 0 0; +#X connect 21 0 20 0; +#X connect 22 0 19 1; +#X connect 23 0 0 0; +#X connect 24 0 21 0; +#X connect 25 0 4 2; +#X connect 26 0 8 1; +#X connect 27 0 21 1; +#X connect 28 0 7 0; +#X connect 30 0 18 0; +#X connect 31 0 0 0; +#X coords 0 0 1 1 210 110 1; +#X restore 33 325 pd audio demo; +#X connect 2 0 3 0; +#X connect 2 1 6 0; +#X connect 2 2 7 0; +#X connect 2 2 15 0; +#X connect 4 0 16 0; +#X connect 5 0 2 0; +#X connect 7 0 8 0; +#X connect 7 0 35 0; +#X connect 8 1 10 0; +#X connect 9 0 2 0; +#X connect 11 0 13 0; +#X connect 12 0 2 0; +#X connect 13 0 12 0; +#X connect 14 0 24 0; +#X connect 16 0 19 0; +#X connect 17 0 18 0; +#X connect 18 0 16 0; +#X connect 18 1 16 1; +#X connect 19 0 2 0; +#X connect 24 0 13 0; +#X connect 24 1 13 1; diff --git a/help/image-help.pd b/help/image-help.pd new file mode 100644 index 0000000..12a5e9f --- /dev/null +++ b/help/image-help.pd @@ -0,0 +1,104 @@ +#N canvas 150 138 585 548 10; +#X obj 0 0 cnv 8 100 60 empty empty image 20 20 1 18 -262144 -1109 +0; +#X text 14 510 (c) moonix: Antoine Rousseau 2004; +#X text 118 15 image viewer; +#X text 79 33 usage: image image_symbol [type]; +#X text 97 48 if type=0 (or absent) \, image_symbol is a file.; +#X text 444 63 see "load" and "set"; +#X text 98 63 if type=1 \, image_symbol means a pre-loaded image \; +; +#X text 248 510 \, but it's a hack of Gunter Geiger's image...; +#X obj 112 134 cnv 15 80 40 empty empty empty 20 12 0 14 -1 -66577 +0; +#X obj 122 148 image play.gif 0; +#X obj 348 216 cnv 15 20 20 empty empty empty 20 12 0 14 -1 -66577 +0; +#X obj 372 197 t a; +#X msg 424 105 open play.gif; +#X msg 425 125 open playy.gif; +#X msg 424 144 open rec.gif; +#X msg 424 162 open pause.gif; +#X msg 424 180 open sinw.gif; +#X msg 425 198 open squarew.gif; +#X msg 425 215 open saww.gif; +#X obj 360 227 image play.gif 0; +#X obj 136 148 image rec.gif 0; +#X obj 152 148 image pause.gif 0; +#X obj 185 144 image sinw.gif 0; +#X obj 185 156 image squarew.gif 0; +#X obj 185 168 image saww.gif 0; +#N canvas 183 192 77 40 /SUBPATCH/ 0; +#X obj 87 205 t a; +#X msg 127 127 open sinw.gif; +#X msg 146 150 open squarew.gif; +#X msg 165 171 open saww.gif; +#X obj -1 0 tgl 40 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; +#X obj 0 1 cnv 15 40 40 empty empty empty 20 12 0 14 -1 -66577 0; +#X obj 26 20 image sinw.gif 0; +#X obj 127 84 i; +#X obj 153 85 + 1; +#X obj 179 85 mod 3; +#X obj 127 105 sel 0 1 2; +#X obj 127 63 b; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 11 0; +#X connect 7 0 8 0; +#X connect 7 0 10 0; +#X connect 8 0 9 0; +#X connect 9 0 7 1; +#X connect 10 0 1 0; +#X connect 10 1 2 0; +#X connect 10 2 3 0; +#X connect 11 0 7 0; +#X coords 0 0 1 1 40 40 1; +#X restore 246 133 pd; +#X text 241 118 click !; +#X obj 65 348 t f f; +#X obj 65 410 pack s s; +#X msg 65 430 load \$1 \$2; +#X msg 295 397 set \$1; +#X obj 298 304 hsl 128 15 0 63 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 295 326 i; +#X obj 202 446 image d15 1; +#X obj 295 349 change; +#X obj 65 370 makesymbol d%s; +#X obj 95 390 makesymbol d/d%s.gif; +#X obj 295 376 makesymbol d%s; +#X text 6 253 For animations \, it's beter to preload images:; +#X obj 402 377 loadbang; +#X msg 402 397 open rec.gif; +#X text 95 274 1: load img_sym file; +#X text 291 287 2: set img_sym; +#X text 270 443 rem: when a img_symbol is loaded \, it; +#X text 305 455 can be used in any image object.; +#X text 17 94 ONLY GIF FILES ACCEPTED !! (because of Tk...); +#X msg 62 276 64; +#X obj 63 299 until; +#X obj 64 325 float; +#X obj 101 325 + 1; +#X connect 12 0 11 0; +#X connect 13 0 11 0; +#X connect 14 0 11 0; +#X connect 15 0 11 0; +#X connect 16 0 11 0; +#X connect 17 0 11 0; +#X connect 18 0 11 0; +#X connect 27 0 35 0; +#X connect 27 1 36 0; +#X connect 28 0 29 0; +#X connect 31 0 32 0; +#X connect 32 0 34 0; +#X connect 34 0 37 0; +#X connect 35 0 28 0; +#X connect 36 0 28 1; +#X connect 37 0 30 0; +#X connect 39 0 40 0; +#X connect 46 0 47 0; +#X connect 47 0 48 0; +#X connect 48 0 27 0; +#X connect 48 0 49 0; +#X connect 49 0 48 1; diff --git a/help/joystik-help.pd b/help/joystik-help.pd new file mode 100644 index 0000000..7915d33 --- /dev/null +++ b/help/joystik-help.pd @@ -0,0 +1,44 @@ +#N canvas 42 155 422 423 10; +#X obj 173 137 tgl 20 1 empty empty empty 20 8 0 8 -262144 -1 -1 1 +1; +#X text 103 121 in order to work.; +#X text 25 391 (c) Antoine Rousseau 2001; +#X obj 233 236 route 0 1; +#X obj 307 235 route 0 1; +#X obj 307 267 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X obj 336 268 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X floatatom 225 265 4 0 0; +#X floatatom 262 265 4 0 0; +#X obj 45 206 joystik; +#X obj 24 236 route 0 1; +#X obj 112 238 route 0 1; +#X obj 112 270 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X obj 141 270 tgl 15 0 empty empty empty 8 -8 0 10 -262144 -1 -1 0 +1; +#X floatatom 17 267 4 0 0; +#X floatatom 53 267 4 0 0; +#X obj 21 19 joystik; +#X text 104 109 joystiks must be switched on; +#X text 36 290 Axis; +#X text 112 291 Buttons; +#X text 78 20 A joystik reporter.; +#X text 28 55 args: [joystick number [is_usb]]; +#X obj 233 207 joystik 1 0; +#X text 22 345 CAUTION: usb untested !; +#X connect 0 0 9 0; +#X connect 0 0 22 0; +#X connect 3 0 7 0; +#X connect 3 1 8 0; +#X connect 4 0 5 0; +#X connect 4 1 6 0; +#X connect 9 0 10 0; +#X connect 9 1 11 0; +#X connect 10 0 14 0; +#X connect 10 1 15 0; +#X connect 11 0 12 0; +#X connect 11 1 13 0; +#X connect 22 0 3 0; +#X connect 22 1 4 0; diff --git a/help/makecolor-help.pd b/help/makecolor-help.pd new file mode 100644 index 0000000..ac52e81 --- /dev/null +++ b/help/makecolor-help.pd @@ -0,0 +1,18 @@ +#N canvas 36 264 527 298 10; +#X text 27 268 (c) Antoine Rousseau 2001; +#X obj 18 27 makecolor; +#X text 91 22 A color-symbol builder \, transforming RGB values in +one hexa symbol.; +#X obj 161 149 makecolor; +#X symbolatom 161 186 10 0 0; +#X floatatom 144 85 5 0 0; +#X floatatom 190 85 5 0 0; +#X floatatom 235 86 5 0 0; +#X obj 161 127 b; +#X connect 3 0 4 0; +#X connect 5 0 3 0; +#X connect 6 0 3 1; +#X connect 6 0 8 0; +#X connect 7 0 3 2; +#X connect 7 0 8 0; +#X connect 8 0 3 0; diff --git a/help/mknob-help.pd b/help/mknob-help.pd new file mode 100644 index 0000000..90f4fb2 --- /dev/null +++ b/help/mknob-help.pd @@ -0,0 +1,53 @@ +#N canvas 19 167 677 325 10; +#X obj 0 0 cnv 8 100 60 empty empty mknob 20 20 1 18 -262144 -1109 +0; +#X floatatom 55 149 5 0 0 0 - - -; +#X floatatom 55 68 5 0 0 0 - - -; +#X text 104 208 Just an adaptation of musil's slider.; +#X obj 138 224 hsl 128 15 0 127 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X text 103 222 See:; +#X msg 3 107 set \$1; +#X floatatom 190 114 5 0 0 0 - - -; +#X obj 190 95 r foo-snd; +#X floatatom 190 60 5 0 0 0 - - -; +#X obj 190 76 s foo-rcv; +#X text 135 12 gui-round-knob; +#X text 2 302 (c) moonix: Antoine Rousseau 2003; +#X obj 149 57 mknob 25 100 0 100 0 0 foo-snd foo-rcv empty -2 -6 192 +8 -225271 -1 -1 0 1; +#X obj 55 85 mknob 30 100 0 127 0 0 empty empty empty -2 -6 0 8 -241291 +-24198 -1 0 1; +#X obj 55 126 mknob 15 100 127 0 0 0 empty empty empty -2 -6 0 8 -258699 +-24198 -1 0 1; +#X text 306 40 "mouse" parameter sets mouse; +#X text 309 50 excursion for full range.; +#X text 309 62 Set it with "size" parameter:; +#X obj 398 201 mknob 25 -1 0 127 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X msg 369 96 size 25 300; +#X msg 398 119 size 25 10; +#X text 452 96 low sensibility; +#X text 474 120 high sens; +#X text 494 142 default; +#X msg 413 141 size 25 100; +#X text 497 164 angular control; +#X msg 427 165 size 25 0; +#X text 518 187 full angular control; +#X msg 443 188 size 25 -1; +#X text 273 253 Note: there is in the sources a patch named mknob.pd.tk.diff +to add (in pd.tk) mknob in the Pd "Put" menu \, and to give the hotkey +"Alt-k" to it. It will only work for Pd0.37 \, but it can help to do +the modif by hand for another version.; +#X connect 2 0 14 0; +#X connect 6 0 14 0; +#X connect 8 0 7 0; +#X connect 9 0 10 0; +#X connect 14 0 15 0; +#X connect 15 0 6 0; +#X connect 15 0 1 0; +#X connect 20 0 19 0; +#X connect 21 0 19 0; +#X connect 25 0 19 0; +#X connect 27 0 19 0; +#X connect 29 0 19 0; diff --git a/help/panvol~-help.pd b/help/panvol~-help.pd new file mode 100644 index 0000000..f7ad351 --- /dev/null +++ b/help/panvol~-help.pd @@ -0,0 +1,34 @@ +#N canvas 117 381 340 290 10; +#X obj 0 0 cnv 8 100 60 empty empty panvol~ 10 20 1 18 -262144 -1109 +0; +#X text 3 269 (c) Moonix: Antoine Rousseau 2003; +#X text 132 12 pan & volume; +#X obj 138 69 hsl 60 10 -45 45 0 0 empty empty pan -2 -6 0 8 -262144 +-1 -1 2950 1; +#X obj 238 61 vsl 10 60 0 1 0 0 empty empty vol 0 -8 0 8 -262144 -1 +-1 5900 1; +#X floatatom 135 85 5 0 0; +#X floatatom 238 127 5 0 0; +#X obj 113 141 panvol~; +#X obj 94 190 unsig~ 100; +#X floatatom 94 210 5 0 0; +#X obj 60 85 osc~ 440; +#X obj 173 190 unsig~ 100; +#X floatatom 173 210 5 0 0; +#X obj 94 170 envrms~; +#X obj 173 170 envrms~; +#X obj 60 104 *~ 2; +#X msg 174 49 0; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 5 0 7 1; +#X connect 6 0 7 2; +#X connect 7 0 13 0; +#X connect 7 1 14 0; +#X connect 8 0 9 0; +#X connect 10 0 15 0; +#X connect 11 0 12 0; +#X connect 13 0 8 0; +#X connect 14 0 11 0; +#X connect 15 0 7 0; +#X connect 16 0 3 0; diff --git a/help/pause.gif b/help/pause.gif new file mode 100644 index 0000000..684f755 Binary files /dev/null and b/help/pause.gif differ diff --git a/help/play.gif b/help/play.gif new file mode 100644 index 0000000..10ae809 Binary files /dev/null and b/help/play.gif differ diff --git a/help/playy.gif b/help/playy.gif new file mode 100644 index 0000000..c710c7e Binary files /dev/null and b/help/playy.gif differ diff --git a/help/popen-help.pd b/help/popen-help.pd new file mode 100644 index 0000000..e37d8e9 --- /dev/null +++ b/help/popen-help.pd @@ -0,0 +1,68 @@ +#N canvas 0 195 644 383 10; +#X obj 0 0 cnv 8 100 60 empty empty popen 10 20 1 18 -262144 -1109 +0; +#X text 13 362 (c) Moonix: Antoine Rousseau 2003; +#X msg 31 74 open process; +#X text 12 57 open: popen for writing; +#X msg 240 76 ropen process; +#X text 221 59 ropen: popen for reading; +#X msg 466 76 close; +#X text 428 60 close (quit) current process; +#X text 108 13 processus in/out (linux only); +#X text 108 26 DANGEROUS: deadlocks are easy!!!!; +#N canvas 0 0 850 359 example 0; +#X obj 458 194 popen; +#X msg 516 167 close; +#X obj 82 311 popen; +#X msg 151 261 close; +#X msg 76 190 list cat to where you want; +#X msg 24 145 open cat > /tmp/tmp_fifo; +#X msg 431 138 ropen cat /tmp/tmp_fifo; +#X obj 38 89 system; +#X msg 38 67 mkfifo /tmp/tmp_fifo; +#X obj 76 258 symbol \;; +#X obj 76 236 t b a; +#X symbolatom 433 284 0 0 0 0 - - -; +#X text 10 17 example: fifo read/write. RESPECT THE NUMBERS for commands +!; +#X text 430 120 3: open for reading; +#X msg 92 213 list Caution not to lock your computer...; +#X text 517 183 6: close reading process; +#X obj 433 260 l2s; +#X obj 458 227 print ropen; +#X text 76 173 4: write to fifo (as many times you want); +#X text 36 46 1: create the fifo (if not done); +#X text 147 244 5: close writing process FIRST; +#X text 23 125 2: open the fifo for writing FIRST; +#X text 503 248 Caution: popen/ropen waits for a " \; "; +#X text 565 260 to send its buffer (pd style).; +#X connect 0 0 17 0; +#X connect 0 0 16 0; +#X connect 1 0 0 0; +#X connect 3 0 2 0; +#X connect 4 0 10 0; +#X connect 5 0 2 0; +#X connect 6 0 0 0; +#X connect 8 0 7 0; +#X connect 9 0 2 0; +#X connect 10 0 9 0; +#X connect 10 1 2 0; +#X connect 14 0 10 0; +#X connect 16 0 11 0; +#X restore 19 161 pd example; +#X obj 31 109 popen; +#X text 20 191 Remarks:; +#X text 46 204 The danger here comes from the fact processes lauched +by; +#X text 47 215 popen runs concurrently with pd: if they are blocking +\, pd; +#X text 46 228 is blocking too. Very dangerous if pd has real-time +priority: it blocks all the sytem. You have to switch off the computer... +; +#X text 47 267 It's much safer to use netsend/netreceive in conjonction +with pdsend/pdreceive.; +#X obj 206 333 system; +#X text 46 297 You can use "at now" to lauch programs totally independantly +from Pd:; +#X msg 206 313 echo xclock -display 0:0 | at now; +#X connect 19 0 17 0; diff --git a/help/readsfv~-help.pd b/help/readsfv~-help.pd new file mode 100644 index 0000000..5870912 --- /dev/null +++ b/help/readsfv~-help.pd @@ -0,0 +1,60 @@ +#N canvas 117 77 546 422 10; +#X obj 0 0 cnv 8 100 60 empty empty readsfv~ 10 20 1 18 -262144 -1109 +0; +#X text 4 400 (c) Moonix: Antoine Rousseau 2003; +#X obj 124 367 dac~; +#X obj 132 331 readsfv~; +#X obj 132 188 delay 20; +#X msg 132 207 start; +#X msg 193 207 1; +#X obj 132 158 bng 15 250 50 0 empty empty play -25 4 0 8 -24198 -1 +-1; +#X obj 183 351 s replay; +#X obj 132 60 r replay; +#X obj 159 284 symbol; +#X msg 159 304 open \$1; +#X msg 229 283 symbol /usr/local/lib/pd/doc/sound/bell.aiff; +#X msg 229 262 symbol ../../sound/bell.aiff; +#X msg 47 298 speed \$1; +#X obj 266 239 openpanel; +#X obj 266 220 bng 15 250 50 0 empty empty open 0 -6 1 8 -195568 -1 +-1; +#X obj 132 126 spigot; +#X obj 169 109 tgl 15 1 empty empty loop 0 -6 1 8 -241291 -1 -1 1 1 +; +#X obj 47 58 vsl 15 128 0.08 8 1 0 empty empty speed 0 -8 1 8 -260818 +-1 -1 6965 1; +#X obj 1 57 init 1; +#X obj 47 278 f; +#X text 171 207 (or; +#X text 220 207 ); +#X obj 57 253 b; +#X obj 113 106 del 100; +#X text 129 8 read a big soundfile in direct-to-disk mode; +#X text 131 20 at variable speed.; +#X text 230 104 read manual of; +#X text 390 103 for more details...; +#X obj 335 102 readsf~; +#X connect 3 0 2 0; +#X connect 3 0 2 1; +#X connect 3 1 8 0; +#X connect 4 0 5 0; +#X connect 5 0 3 0; +#X connect 5 0 24 0; +#X connect 7 0 4 0; +#X connect 7 0 10 0; +#X connect 9 0 25 0; +#X connect 10 0 11 0; +#X connect 11 0 3 0; +#X connect 12 0 10 1; +#X connect 13 0 10 1; +#X connect 14 0 3 0; +#X connect 15 0 10 1; +#X connect 16 0 15 0; +#X connect 17 0 7 0; +#X connect 18 0 17 1; +#X connect 19 0 21 0; +#X connect 20 0 19 0; +#X connect 21 0 14 0; +#X connect 24 0 21 0; +#X connect 25 0 17 0; diff --git a/help/rec.gif b/help/rec.gif new file mode 100644 index 0000000..d49b027 Binary files /dev/null and b/help/rec.gif differ diff --git a/help/relativepath-help.pd b/help/relativepath-help.pd new file mode 100644 index 0000000..b056f4a --- /dev/null +++ b/help/relativepath-help.pd @@ -0,0 +1,13 @@ +#N canvas 14 323 660 379 10; +#X text 17 352 (c) Antoine Rousseau 2004; +#X obj 33 108 absolutepath; +#X symbolatom 33 131 0 0 0; +#X msg 33 51 symbol absolutepath.pd; +#X obj 33 220 relativepath; +#X symbolatom 33 245 0 0 0; +#X text 14 6 absolutepath / relativepath : use filenames relatively +to the patch's path.; +#X connect 1 0 2 0; +#X connect 2 0 4 0; +#X connect 3 0 1 0; +#X connect 4 0 5 0; diff --git a/help/s2f-help.pd b/help/s2f-help.pd new file mode 100644 index 0000000..2192924 --- /dev/null +++ b/help/s2f-help.pd @@ -0,0 +1,18 @@ +#N canvas 106 74 492 266 10; +#X obj 0 0 cnv 8 100 60 empty empty s2f 10 20 1 18 -262144 -1109 0 +; +#X text 1 244 (c) Moonix: Antoine Rousseau 2003; +#X text 129 8 symbol to float converter; +#X obj 197 159 s2f; +#X floatatom 197 184 0 0 0; +#X symbolatom 197 142 0 0 0; +#X obj 345 105 makesymbol %s; +#X msg 48 84 symbol 0.0003125foo; +#X msg 197 85 symbol 54.123e-3bar; +#X msg 345 85 13.25; +#X connect 3 0 4 0; +#X connect 5 0 3 0; +#X connect 6 0 5 0; +#X connect 7 0 5 0; +#X connect 8 0 5 0; +#X connect 9 0 6 0; diff --git a/help/sarray-help.pd b/help/sarray-help.pd new file mode 100644 index 0000000..157d245 --- /dev/null +++ b/help/sarray-help.pd @@ -0,0 +1,93 @@ +#N canvas 158 412 745 484 10; +#X obj 0 0 cnv 8 100 60 empty empty sarray 10 20 1 18 -262144 -1109 +0; +#X text 2 467 (c) Moonix: Antoine Rousseau 2003; +#X msg 74 275 1; +#X msg 103 275 2; +#X msg 131 275 3; +#X symbolatom 139 356 10 0 0; +#X msg 533 269 reset; +#X text 109 12 shared array of symbols; +#X obj 47 146 sarray foo 8; +#X text 23 48 1) set the length; +#X msg 47 71 setlen 10; +#X text 236 43 2) set the nth element; +#X msg 266 85 set 2 two; +#X msg 274 106 set 3 three; +#X obj 258 169 sarray foo; +#X msg 129 110 print; +#X msg 44 299 get \$1; +#X obj 44 320 sarray foo; +#X obj 44 339 route bang; +#X msg 159 275 4; +#X obj 44 359 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 44 275 0; +#X text 12 256 3) get the nth symbol (first:0); +#X obj 533 289 sarray foo; +#X text 1 376 (bang when empty); +#X text 298 252 4) dump the whole array; +#X obj 299 379 sarray foo; +#X msg 299 272 dump; +#X obj 299 400 print dump; +#X msg 334 325 dump _null_; +#X msg 334 345 dump *?!; +#X text 315 298 specify a default symbol; +#X text 329 309 for empty elements; +#X obj 472 175 sarray foo; +#X text 494 85 specify a default symbol; +#X text 494 97 for empty elements; +#X msg 294 147 print; +#X msg 428 146 print; +#X text 531 251 6) clear the sarray; +#X msg 578 269 print; +#X text 6 165 args: sarray name [length]; +#X text 258 193 args: set [empty_symbol] first_index sym1 [sym2 [sym3...]]] +; +#X text 286 425 args: dump [empty_symbol]; +#X msg 258 61 set 0 zero; +#X text 453 43 3) set many elements; +#X text 533 134 ...erase one element; +#X msg 281 127 set 4 four; +#X msg 57 93 setlen 4; +#X msg 534 149 set _niet_ 3 _niet_; +#X msg 499 113 set _ 0 zero un _ trois _ cinq; +#X msg 472 60 set 0 zero ein zwei drei; +#X text 528 328 7) switch to another array; +#X obj 523 370 sarray foo2 4; +#X msg 523 351 set 0 zero2 one2 two2 three2; +#X obj 528 442 sarray; +#X msg 528 402 print; +#X msg 577 403 setarray foo; +#X msg 577 422 setarray foo2; +#X connect 2 0 16 0; +#X connect 3 0 16 0; +#X connect 4 0 16 0; +#X connect 6 0 23 0; +#X connect 10 0 8 0; +#X connect 12 0 14 0; +#X connect 13 0 14 0; +#X connect 15 0 8 0; +#X connect 16 0 17 0; +#X connect 17 0 18 0; +#X connect 18 0 20 0; +#X connect 18 1 5 0; +#X connect 19 0 16 0; +#X connect 21 0 16 0; +#X connect 26 0 28 0; +#X connect 27 0 26 0; +#X connect 29 0 26 0; +#X connect 30 0 26 0; +#X connect 36 0 14 0; +#X connect 37 0 33 0; +#X connect 39 0 23 0; +#X connect 43 0 14 0; +#X connect 46 0 14 0; +#X connect 47 0 8 0; +#X connect 48 0 33 0; +#X connect 49 0 33 0; +#X connect 50 0 33 0; +#X connect 53 0 52 0; +#X connect 55 0 54 0; +#X connect 56 0 54 0; +#X connect 57 0 54 0; diff --git a/help/saww.gif b/help/saww.gif new file mode 100644 index 0000000..32997ad Binary files /dev/null and b/help/saww.gif differ diff --git a/help/sfread2~-help.pd b/help/sfread2~-help.pd new file mode 100644 index 0000000..ad8ae16 --- /dev/null +++ b/help/sfread2~-help.pd @@ -0,0 +1,60 @@ +#N canvas 38 250 582 490 10; +#X obj 0 0 cnv 8 100 60 empty empty sfread2~ 10 20 1 18 -262144 -1109 +0; +#X text 2 459 (c) Moonix: Antoine Rousseau 2003; +#X text 66 390 Change "mlockall(MCL_FUTURE)" with "mlockall(MCL_CURRENT) +; +#X obj 155 262 sfread2~ 2; +#X msg 155 202 open \$1; +#X obj 19 151 bng 15 250 50 0 empty empty play 20 8 1 8 -24198 -1 -1 +; +#X msg 278 225 loop \$1; +#X obj 278 207 tgl 15 1 empty empty loop 20 8 0 8 -241291 -1 -1 1 1 +; +#X obj 57 103 tgl 15 1 empty empty interpolation 20 8 1 8 -257472 -1 +-1 1 1; +#X msg 57 121 interp \$1; +#X obj 458 181 vsl 15 128 -8 8 0 0 empty empty speed 0 -8 1 8 -260818 +-1 -1 7144 1; +#X text 135 12 soundfile reader at variable speed (possibly negative) +\, whith 4-point interpolation and loop.; +#X obj 154 296 dac~; +#X obj 155 92 openpanel; +#X obj 155 72 bng 15 250 50 0 empty empty open 0 -6 1 8 -166441 -1 +-1; +#X obj 18 179 bng 15 250 50 0 empty empty stop 20 8 1 8 -1 -1 -1; +#X msg 18 196 0; +#X obj 148 339 sfread~; +#X text 43 341 read manual of; +#X text 202 339 for more details...; +#X text 235 159 resets sound to position; +#X text 234 148 start position in samples; +#X msg 238 174 index 20000; +#X obj 497 177 loadbang; +#X msg 497 196 1; +#X msg 261 99 symbol /usr/local/lib/pd/doc/sound/voice.wav; +#X msg 261 78 symbol ../../sound/voice.wav; +#X text 66 414 If not \, the whole file will be loaded in memory when +opened (use of C function mmap()).; +#X text 66 401 in s_linux.c... SORRY \, I mean in s_inter.c (since +0.37...); +#X text 59 378 CAUTION: you should hack pd sources to have d-t-d working. +; +#X connect 3 0 12 0; +#X connect 3 1 12 1; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 6 0 3 0; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 9 0 3 0; +#X connect 10 0 3 1; +#X connect 13 0 4 0; +#X connect 14 0 13 0; +#X connect 15 0 16 0; +#X connect 16 0 3 0; +#X connect 22 0 3 0; +#X connect 23 0 24 0; +#X connect 24 0 10 0; +#X connect 25 0 4 0; +#X connect 26 0 4 0; diff --git a/help/sin.gif b/help/sin.gif new file mode 100644 index 0000000..c84ad79 Binary files /dev/null and b/help/sin.gif differ diff --git a/help/sinw.gif b/help/sinw.gif new file mode 100644 index 0000000..8bedc66 Binary files /dev/null and b/help/sinw.gif differ diff --git a/help/slist-help.pd b/help/slist-help.pd new file mode 100644 index 0000000..f499120 --- /dev/null +++ b/help/slist-help.pd @@ -0,0 +1,61 @@ +#N canvas 459 312 690 375 10; +#X obj 0 0 cnv 8 100 60 empty empty slist 10 20 1 18 -262144 -1109 +0; +#X text 3 354 (c) Moonix: Antoine Rousseau 2003; +#X text 109 12 shared list of symbols \, with a "find" feature; +#X obj 80 107 slist foo; +#X obj 261 100 slist foo; +#X text 24 55 1) fill the slist; +#X msg 261 79 len; +#X text 260 58 2) get the slist length; +#X floatatom 319 121 5 0 0; +#X obj 480 106 slist foo; +#X msg 451 79 1; +#X msg 480 79 2; +#X msg 508 79 3; +#X symbolatom 509 127 10 0 0; +#X obj 157 218 slist foo; +#X text 448 59 3) get the nth symbol (first:1); +#X msg 21 189 find boo; +#X msg 225 189 find bar; +#X floatatom 157 242 5 0 0; +#X msg 91 189 find bee; +#X msg 157 189 find baa; +#X obj 548 212 slist foo; +#X text 21 168 4) find the index of a symbol (0 = not found); +#X msg 548 192 reset; +#X msg 144 77 add baa; +#X msg 26 77 add boo \, add bee; +#X obj 378 223 slist foo; +#X text 364 169 5) print to console; +#X text 546 171 6) clear the slist; +#X msg 378 203 print; +#X text 383 184 (debug); +#X obj 256 318 slist foo2; +#X text 256 271 7) switch to another slist; +#X obj 476 345 slist; +#X msg 503 296 setlist foo; +#X msg 503 318 setlist foo2; +#X msg 460 296 print; +#X msg 256 297 add boo2 \, add bee2 \, add baa2; +#X msg 212 297 print; +#X connect 4 2 8 0; +#X connect 6 0 4 0; +#X connect 9 1 13 0; +#X connect 10 0 9 0; +#X connect 11 0 9 0; +#X connect 12 0 9 0; +#X connect 14 0 18 0; +#X connect 16 0 14 0; +#X connect 17 0 14 0; +#X connect 19 0 14 0; +#X connect 20 0 14 0; +#X connect 23 0 21 0; +#X connect 24 0 3 0; +#X connect 25 0 3 0; +#X connect 29 0 26 0; +#X connect 34 0 33 0; +#X connect 35 0 33 0; +#X connect 36 0 33 0; +#X connect 37 0 31 0; +#X connect 38 0 31 0; diff --git a/help/squarew.gif b/help/squarew.gif new file mode 100644 index 0000000..3e689c7 Binary files /dev/null and b/help/squarew.gif differ diff --git a/help/ssaw~-help.pd b/help/ssaw~-help.pd new file mode 100644 index 0000000..25903d1 --- /dev/null +++ b/help/ssaw~-help.pd @@ -0,0 +1,21 @@ +#N canvas 106 74 492 266 10; +#X obj 0 0 cnv 8 100 60 empty empty ssaw 10 20 1 18 -262144 -1109 0 +; +#X text 8 243 (c) Moonix: Antoine Rousseau 2004; +#X obj 162 103 ssaw~ 440; +#X obj 163 149 *~; +#X obj 162 77 mtof; +#X floatatom 161 57 5 0 0 0 - - -; +#X floatatom 207 77 0 0 0 0 - - -; +#X obj 197 128 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 159 193 dac~; +#X text 124 19 sweet sawtooth generator; +#X text 121 32 (not to much aliasing below 10kHz); +#X connect 2 0 3 0; +#X connect 3 0 8 0; +#X connect 3 0 8 1; +#X connect 4 0 6 0; +#X connect 4 0 2 0; +#X connect 5 0 4 0; +#X connect 7 0 3 1; diff --git a/help/tabdump2-help.pd b/help/tabdump2-help.pd new file mode 100644 index 0000000..b69458c --- /dev/null +++ b/help/tabdump2-help.pd @@ -0,0 +1,31 @@ +#N canvas 21 53 496 358 10; +#X obj 13 21 tabdump2; +#X obj 187 37 tabdump; +#X text 22 332 (c) Antoine Rousseau 2004; +#X text 104 21 dump the contents of a table as a list; +#X text 104 37 like zexy's; +#X text 244 38 but with min/max dumping limits.; +#N canvas 0 0 450 300 graph5 0; +#X array \$0-array 10 float 0; +#X coords 0 1 9 0 100 80 1; +#X restore 330 71 graph; +#X obj 17 132 s \$0-array; +#X msg 17 112 0 0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9; +#X obj 17 92 loadbang; +#X obj 34 243 tabdump2 \$0-array; +#X obj 34 269 l2s; +#X symbolatom 34 293 0 0 0 0 - - -; +#X obj 258 204 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 22 204 dump 0 5; +#X msg 95 203 dump 5 10; +#X text 18 177 dump N M: from N to (M-1); +#X msg 174 203 dump 5 6; +#X connect 8 0 7 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 11 0 12 0; +#X connect 13 0 10 0; +#X connect 14 0 10 0; +#X connect 15 0 10 0; +#X connect 17 0 10 0; diff --git a/help/tabenv-help.pd b/help/tabenv-help.pd new file mode 100644 index 0000000..cb719d0 --- /dev/null +++ b/help/tabenv-help.pd @@ -0,0 +1,25 @@ +#N canvas 205 155 534 360 10; +#X text 22 332 (c) Antoine Rousseau 2001; +#X obj 21 19 tabenv; +#X text 78 21 A envelope follower for table (not in real-time).; +#X text 35 65 args: arrayname [computation_num_points [output_period]] +; +#X text 147 151 change the array; +#X msg 64 181 reset; +#X msg 64 152 set Array1; +#X obj 64 255 tabenv Array0; +#X floatatom 64 283 5 0 0; +#X msg 64 209 0 44100; +#X text 125 209 compute 1 sec from the beginning; +#X text 126 181 reset the computation buffers; +#X obj 258 86 env~; +#X text 294 85 ); +#X text 217 86 (like; +#X text 151 84 ); +#X text 47 86 (like; +#X obj 90 86 tabplay~; +#X text 79 38 (in fact it's a mix between tabplay and env~); +#X connect 5 0 7 0; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 9 0 7 0; diff --git a/help/tabreadl-help.pd b/help/tabreadl-help.pd new file mode 100644 index 0000000..feebabe --- /dev/null +++ b/help/tabreadl-help.pd @@ -0,0 +1,26 @@ +#N canvas 502 181 672 415 10; +#X obj 10 11 tabreadl; +#X text 22 332 (c) Antoine Rousseau 2004; +#X floatatom 15 173 0 0 0; +#X floatatom 15 278 0 0 0; +#N canvas 0 0 450 300 graph1 0; +#X array \$0-array 10 float 0; +#X coords 0 0 10 10 250 200 1; +#X restore 362 179 graph; +#X text 60 276 output = array99[index]; +#X text 34 50 click here to initialize; +#X text 159 236 creation argument; +#X text 155 254 gives array name; +#X text 137 204 change array name; +#X msg 25 204 set \$0-array99; +#X msg 33 65 resize 10 \, bounds 0 0 10 10 \, xlabel -0.5 0 1 2 3 4 +5 6 7 8 9 10 \, ylabel -1 0 1 2 3 4 5 6 7 8 9 10 \, 0 1 4 2 8 5 6 1 +4 2 8; +#X obj 34 139 s \$0-array; +#X text 110 8 - linear interpolating read from a table; +#X text 46 174 index(float); +#X obj 15 245 tabreadl \$0-array; +#X connect 2 0 15 0; +#X connect 10 0 15 0; +#X connect 11 0 12 0; +#X connect 15 0 3 0; diff --git a/help/tabsort-help.pd b/help/tabsort-help.pd new file mode 100644 index 0000000..805f12a --- /dev/null +++ b/help/tabsort-help.pd @@ -0,0 +1,32 @@ +#N canvas 118 208 534 360 10; +#X text 22 332 (c) Antoine Rousseau 2001; +#X floatatom 39 303 5 0 0 0 - - -; +#X obj 21 19 tabsort; +#X text 20 58 args: source_table dest_table; +#N canvas 0 0 450 300 graph29 0; +#X array source 10 float 1; +#A 0 -0.0571429 -0.985715 -0.942858 -0.857143 -0.757143 -0.542857 -0.171429 +0.528571 0.842858 0.914287; +#X coords 0 1 9 -1 200 140 1; +#X restore 51 92 graph; +#N canvas 0 0 450 300 graph29 0; +#X array dest 10 float 1; +#A 0 9 8 7 0 6 5 4 3 2 1; +#X coords 0 10 9 0 200 140 1; +#X restore 304 89 graph; +#X obj 39 282 tabsort source dest; +#X msg 39 262 10; +#X text 79 12 write to dest_table the indices of source_table's elements +sorted by decreasing order (biggest first); +#X text 38 248 sort the n first elements; +#X obj 304 264 tabread dest; +#X obj 304 285 tabread source; +#X floatatom 304 246 5 0 0 0 - - -; +#X floatatom 304 305 5 0 0 0 - - -; +#X text 347 244 try it!; +#X text 300 321 it should decrease with input; +#X connect 6 0 1 0; +#X connect 7 0 6 0; +#X connect 10 0 11 0; +#X connect 11 0 13 0; +#X connect 12 0 10 0; diff --git a/help/tabsort2-help.pd b/help/tabsort2-help.pd new file mode 100644 index 0000000..4f4e29a --- /dev/null +++ b/help/tabsort2-help.pd @@ -0,0 +1,84 @@ +#N canvas 133 15 811 538 10; +#X floatatom 62 381 5 0 0 0 - - -; +#N canvas 0 0 450 300 graph29 0; +#X array source1 100 float 1; +#A 0 -0.0428565 -0.0571422 0.085715 0.228572 0.442858 0.657144 0.871429 +1.08572 1.22857 1.51429 1.72857 1.94286 2.22857 2.37143 2.58571 2.72857 +2.87143 2.94286 3.15714 3.3 3.3 3.44286 3.58571 3.65714 3.72857 3.8 +3.94286 4.01429 4.08571 4.22857 4.3 4.13929 3.97857 3.81786 3.51429 +3.22857 2.8 2.37143 2.3 2.3 2.3 2.37143 2.44286 2.51429 2.51429 2.58572 +2.55 2.37143 2.22857 1.94286 1.72857 1.58572 1.44286 1.44286 1.37144 +1.37144 1.37144 1.44286 1.44286 1.44286 1.44286 1.51429 1.51429 1.58572 +1.65714 1.65714 1.70476 1.75238 1.8 1.87143 2.01429 2.15714 2.22857 +4.58572 4.94286 5.22857 5.44286 5.58572 5.58572 5.39524 5.20477 5.01429 +4.82381 4.63334 4.44286 4.25238 4.06191 3.8 3.72857 3.65715 3.65715 +3.58572 3.58572 4.15715 4.51429 4.58572 4.72858 4.87143 5.08572 5.44286 +; +#X coords 0 10 99 0 200 140 1; +#X restore 60 133 graph; +#N canvas 0 0 450 300 graph29 0; +#X array dest 100 float 0; +#X coords 0 100 99 0 200 140 1; +#X restore 547 129 graph; +#X obj 10 8 tabsort2; +#X text 75 9 2 dimensionnal sort.; +#X text 24 99 args: source_table1 source_table2 dest_table; +#X text 248 8 write to dest_table the indices of the first N source_table1's +elements sorted by decreasing order (biggest first) \, then sort the +"columns" of sqrt(N) indices decreasingly according to their values +in source_table2 (is it clear?).; +#N canvas 0 0 450 300 graph29 0; +#X array source2 100 float 1; +#A 0 7.71429 7.64286 7.64286 7.57143 7.5 7.35714 7.21428 6.92857 6.57143 +6 5.71428 5.57143 5.21428 4.5 4.35714 4.28571 4.28571 4.28571 4.28571 +4.28571 4.42857 4.57143 4.64285 4.78571 4.92857 5.14285 5.35714 5.71428 +6 6.21428 6.42857 6.57143 6.64286 6.64286 6.64286 6.64286 6.57143 6.57143 +6.42857 6.35714 6.28571 6.14286 5.92857 5.78571 5.64286 5.42857 7.85714 +7.92857 8.42857 8.71428 8.92857 8.92857 8.92857 8.92857 8.85714 8.78571 +8.78571 8.78571 8.5 8.28571 8.07143 7.5 7.28571 6.85714 6.57143 5.78571 +5.5 5.21428 4.78571 4.64286 4.64286 4.78571 4.92857 5.07143 5.21428 +5.42857 5.57143 5.71428 5.92857 6.28571 6.5 6.85714 7.14286 7.35714 +7.64286 7.71429 7.78572 7.85714 7.85714 7.85714 7.71429 7.64286 7.5 +7.35714 7.14286 7.07143 7 6.85714 4.5 -0.342857; +#X coords 0 10 99 0 200 140 1; +#X restore 311 131 graph; +#X msg 62 340 100; +#X obj 62 360 tabsort2 source1 source2 dest; +#X obj 500 416 tabread dest; +#X obj 452 362 * 10; +#X obj 500 391 +; +#X floatatom 451 346 5 0 9 0 - - -; +#X obj 528 361 t b f; +#X floatatom 528 344 5 0 9 0 - - -; +#X floatatom 407 485 0 0 0 0 - - -; +#X obj 407 465 tabread source1; +#X obj 557 467 tabread source2; +#X floatatom 557 487 0 0 0 0 - - -; +#X floatatom 527 393 5 0 0 0 - - -; +#X text 433 328 x(columns); +#X text 521 327 y(lines); +#X text 403 504 decrease with x; +#X text 555 505 decrease with y; +#X text 49 305 1) Sort it:; +#X text 381 304 2) Try it:; +#X text 8 520 (c) Antoine Rousseau 2002; +#X floatatom 603 441 5 0 0 0 - - -; +#X text 604 416 index of sources; +#X text 606 426 elements; +#X text 28 396 output=sqrt(N)=the width/height; +#X text 28 410 of the destination "square".; +#X text 61 326 sort the N first elements; +#X connect 8 0 9 0; +#X connect 9 0 0 0; +#X connect 10 0 17 0; +#X connect 10 0 18 0; +#X connect 10 0 28 0; +#X connect 11 0 12 0; +#X connect 12 0 10 0; +#X connect 12 0 20 0; +#X connect 13 0 11 0; +#X connect 14 0 12 0; +#X connect 14 1 12 1; +#X connect 15 0 14 0; +#X connect 17 0 16 0; +#X connect 18 0 19 0; diff --git a/image.c b/image.c new file mode 100644 index 0000000..f38078d --- /dev/null +++ b/image.c @@ -0,0 +1,306 @@ +#include +#include "g_canvas.h" +#include +#include +#include + +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +/* ------------------------ image ----------------------------- */ + +static t_class *image_class; + +typedef struct _image +{ + t_object x_obj; + t_glist * x_glist; + int x_width; + int x_height; + t_symbol* x_image; + int x_type; //0=file 1=tk_image + t_int x_localimage; //localimage "img%x" done +} t_image; + +/* widget helper functions */ + +const char* image_get_filename(t_image *x,char *file) +{ + static char fname[MAXPDSTRING]; + char *bufptr; + int fd; + + fd=open_via_path(canvas_getdir(glist_getcanvas(x->x_glist))->s_name, + file, "",fname, &bufptr, MAXPDSTRING, 1); + if(fd>0){ + fname[strlen(fname)]='/'; + //post("image file: %s",fname); + close(fd); + return fname; + } + else return 0; +} + +void image_drawme(t_image *x, t_glist *glist, int firsttime) +{ + if (firsttime) { + if(x->x_type) { + sys_vgui(".x%x.c create image %d %d -tags %xS\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x); + sys_vgui(".x%x.c itemconfigure %xS -image %s\n", + glist_getcanvas(glist),x,x->x_image->s_name); + } + else { + const char *fname=image_get_filename(x,x->x_image->s_name); + if(!x->x_localimage) { + sys_vgui("image create photo img%x\n",x); + x->x_localimage=1; + } + if(fname) sys_vgui("img%x configure -file %s\n",x,fname); + sys_vgui(".x%x.c create image %d %d -image img%x -tags %xS\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist),x,x); + } + /* TODO callback from gui + sys_vgui("image_size logo"); + */ + } + else { + sys_vgui(".x%x.c coords %xS \ +%d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist)); + } + +} + + +void image_erase(t_image* x,t_glist* glist) +{ + int n; + sys_vgui(".x%x.c delete %xS\n", + glist_getcanvas(glist), x); + +} + + + +/* ------------------------ image widgetbehaviour----------------------------- */ + + +static void image_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + int width, height; + t_image* x = (t_image*)z; + + + width = x->x_width; + height = x->x_height; + *xp1 = text_xpix(&x->x_obj, glist); + *yp1 = text_ypix(&x->x_obj, glist); + *xp2 = text_xpix(&x->x_obj, glist) + width; + *yp2 = text_ypix(&x->x_obj, glist) + height; +} + +static void image_displace(t_gobj *z, t_glist *glist, + int dx, int dy) +{ + t_image *x = (t_image *)z; + x->x_obj.te_xpix += dx; + x->x_obj.te_ypix += dy; + sys_vgui(".x%x.c coords %xSEL %d %d %d %d\n", + glist_getcanvas(glist), x, + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height); + + image_drawme(x, glist, 0); + canvas_fixlinesfor(glist_getcanvas(glist),(t_text*) x); +} + +static void image_select(t_gobj *z, t_glist *glist, int state) +{ + t_image *x = (t_image *)z; + if (state) { + sys_vgui(".x%x.c create rectangle \ +%d %d %d %d -tags %xSEL -outline blue\n", + glist_getcanvas(glist), + text_xpix(&x->x_obj, glist), text_ypix(&x->x_obj, glist), + text_xpix(&x->x_obj, glist) + x->x_width, text_ypix(&x->x_obj, glist) + x->x_height, + x); + } + else { + sys_vgui(".x%x.c delete %xSEL\n", + glist_getcanvas(glist), x); + } + + + +} + + +static void image_activate(t_gobj *z, t_glist *glist, int state) +{ +/* t_text *x = (t_text *)z; + t_rtext *y = glist_findrtext(glist, x); + if (z->g_pd != gatom_class) rtext_activate(y, state);*/ +} + +static void image_delete(t_gobj *z, t_glist *glist) +{ + t_text *x = (t_text *)z; + //canvas_deletelinesfor(glist_getcanvas(glist), x); + canvas_deletelinesfor(glist, x); +} + + +static void image_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_image* s = (t_image*)z; + if (vis) + image_drawme(s, glist, 1); + else + image_erase(s,glist); +} + +/* can we use the normal text save function ?? */ + +static void image_save(t_gobj *z, t_binbuf *b) +{ + t_image *x = (t_image *)z; + binbuf_addv(b, "ssiissi", gensym("#X"),gensym("obj"), + x->x_obj.te_xpix, x->x_obj.te_ypix, + gensym("image"),x->x_image,x->x_type); + binbuf_addv(b, ";"); +} + + +t_widgetbehavior image_widgetbehavior; + +void image_size(t_image* x,t_floatarg w,t_floatarg h) { + x->x_width = w; + x->x_height = h; +} + +void image_color(t_image* x,t_symbol* col) +{ +/* outlet_bang(x->x_obj.ob_outlet); only bang if there was a bang .. + so color black does the same as bang, but doesn't forward the bang +*/ +} + +void image_open(t_gobj *z,t_symbol* file) +{ + t_image* x = (t_image*)z; + const char *fname; + int oldtype=x->x_type; + + + fname=image_get_filename(x,file->s_name); + if(fname){ + x->x_image=file; + x->x_type=0; + if(glist_isvisible(x->x_glist)) { + if(!x->x_localimage) { + sys_vgui("image create photo img%x\n",x); + x->x_localimage=1; + } + sys_vgui("img%x blank\n",x); + sys_vgui("img%x configure -file %s\n",x,fname); + if(oldtype) sys_vgui(".x%x.c itemconfigure %xS -image img%x\n", + glist_getcanvas(x->x_glist),x,x); + } + } +} + +void image_load(t_gobj *z,t_symbol* image,t_symbol* file) +{ + t_image* x = (t_image*)z; + const char *fname; + + fname=image_get_filename(x,file->s_name); + if(fname){ + sys_vgui("image create photo %s -file %s\n",image->s_name,fname); + } +} + +void image_set(t_gobj *z,t_symbol* image) +{ + t_image* x = (t_image*)z; + + x->x_image=image; + x->x_type=1; + + if(glist_isvisible(x->x_glist)) { + sys_vgui(".x%x.c itemconfigure %xS -image %s\n", + glist_getcanvas(x->x_glist),x,x->x_image->s_name); + } +} + + +static void image_setwidget(void) +{ + image_widgetbehavior.w_getrectfn = image_getrect; + image_widgetbehavior.w_displacefn = image_displace; + image_widgetbehavior.w_selectfn = image_select; + image_widgetbehavior.w_activatefn = image_activate; + image_widgetbehavior.w_deletefn = image_delete; + image_widgetbehavior.w_visfn = image_vis; +#if (PD_VERSION_MINOR > 31) + image_widgetbehavior.w_clickfn = NULL; + image_widgetbehavior.w_propertiesfn = NULL; +#endif +#if PD_MINOR_VERSION < 37 + image_widgetbehavior.w_savefn = image_save; +#endif +} + + +static void *image_new(t_symbol* image,int type) +{ + t_image *x = (t_image *)pd_new(image_class); + + x->x_glist = (t_glist*) canvas_getcurrent(); + + x->x_width = 15; + x->x_height = 15; + x->x_type=type; + x->x_localimage=0; + x->x_image = image; + + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void image_setup(void) +{ + image_class = class_new(gensym("image"), (t_newmethod)image_new, 0, + sizeof(t_image),0, A_DEFSYM,A_DEFFLOAT,0); + +/* + class_addmethod(image_class, (t_method)image_size, gensym("size"), + A_FLOAT, A_FLOAT, 0); + + class_addmethod(image_class, (t_method)image_color, gensym("color"), + A_SYMBOL, 0); +*/ + + class_addmethod(image_class, (t_method)image_open, gensym("open"), + A_SYMBOL, 0); + class_addmethod(image_class, (t_method)image_set, gensym("set"), + A_SYMBOL, 0); + class_addmethod(image_class, (t_method)image_load, gensym("load"), + A_SYMBOL, A_SYMBOL, 0); + + image_setwidget(); + class_setwidget(image_class,&image_widgetbehavior); +#if PD_MINOR_VERSION >= 37 + class_setsavefn(image_class,&image_save); +#endif + +} + + diff --git a/joystik.c b/joystik.c new file mode 100644 index 0000000..2c09093 --- /dev/null +++ b/joystik.c @@ -0,0 +1,191 @@ +/* +'pd_joystik' (An external library for Miller Puckette's 'PD' software +adding PC and/or USB joystik control capabilities) + +Copyright (C) 2001 Antoine Rousseau (from the initial file of Joseph A. Sarlo) + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/*0=normal joystick: /dev/jsXX 1=usb joystick: /dev/input/jsXX */ + +static GList *(joy_lists)[2][16]={{0},{0}}; +static int fds[2][16]; + +typedef struct _joystik +{ + t_object t_ob; + t_outlet *x_axis_out; + t_outlet *x_button_out; + guchar x_connected; + guchar x_usb; /*0:normal 1:usb*/ + gushort x_number; /*0 to 15*/ +}t_joystik; + +t_class *joystik_class; + +void joystik_setup(void); +static void joystik_read(GList *l,int fd); + +static void fd_open(int usb,int n) +{ + char filename[128]; + int *fd=&fds[(int)usb][(int)n]; + GList *l=joy_lists[(int)usb][(int)n]; + + if(usb) sprintf(filename,"/dev/input/js%d",n); + else sprintf(filename,"/dev/js%d",n); + + if(*fd<=0){ + *fd = open (filename, O_RDONLY | O_NONBLOCK); + if(*fd<0){ + post("open (%s, O_RDONLY | O_NONBLOCK)",filename); + perror("open"); + return; + } + } + sys_addpollfn(*fd,(t_fdpollfn)joystik_read,(void*)l); + /*post("joystick: adding poll");*/ +} + +static void fd_close(int usb,int n) +{ + int *fd=&fds[(int)usb][(int)n]; + + sys_rmpollfn(*fd); + close(*fd); + *fd=-1; + /*post("joystick: removing poll");*/ +} + +static void joystik_connect(t_joystik *x) +{ + GList *l=joy_lists[x->x_usb][x->x_number]; + + if(g_list_find(l,(void*)x)) return; + + g_list_append(l,(void*)x); + + if(g_list_length(l)==2){ + fd_open(x->x_usb,x->x_number); + } +} +static void joystik_deconnect(t_joystik *x) +{ + GList *l=joy_lists[x->x_usb][x->x_number]; + + if(!g_list_find(l,(void*)x)) return; + + g_list_remove(l,(void*)x); + + if(g_list_length(l)==1){ + fd_close(x->x_usb,x->x_number); + } +} + +static void joystik_float(t_joystik *x,t_floatarg connect) +{ + connect=(connect!=0); + + if(x->x_connected==connect) return; + + if(connect) joystik_connect(x); + else joystik_deconnect(x); + + x->x_connected=connect; +} + +static void *joystik_new(t_float num, t_float usb) +{ + t_joystik *x = (t_joystik *)pd_new(joystik_class); + int n=num; + GList **l=0; + + if((n<0)||(n>16)) { + post("ERROR in joystik_new : device number out of range"); + return (void*)x; + } + + usb=(usb!=0); + x->x_axis_out = outlet_new(&x->t_ob, &s_list); + x->x_button_out = outlet_new(&x->t_ob, &s_list); + + x->x_connected=0; + x->x_usb=usb; + x->x_number=n; + + l=&joy_lists[(int)usb][(int)n]; + + if(!*l) *l=g_list_alloc(); + + return (void *)x; +} + +void joystik_setup(void) +{ + joystik_class = class_new(gensym("joystik"),(t_newmethod)joystik_new, + (t_method)joystik_deconnect, sizeof(t_joystik), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(joystik_class, joystik_float); + + +} + +static void joystik_read(GList *l,int fd) +{ + #define AMP 32767.0 + int rt; + struct js_event e; + t_atom ats[2]; + GList *ltmp; + + while (read (fd, &e, sizeof(struct js_event)) > -1) + { + SETFLOAT(&ats[0],e.number); + if (e.type == JS_EVENT_AXIS) + { + SETFLOAT(&ats[1],e.value/AMP); + ltmp=l; + while(ltmp->next){ + ltmp=ltmp->next; + outlet_list(((t_joystik*)ltmp->data)->x_axis_out,0,2,ats); + } + } + else if (e.type == JS_EVENT_BUTTON) + { + SETFLOAT(&ats[1],e.value); + ltmp=l; + while(ltmp->next){ + ltmp=ltmp->next; + outlet_list(((t_joystik*)ltmp->data)->x_button_out,0,2,ats); + } + } + } +} + diff --git a/mknob.c b/mknob.c new file mode 100644 index 0000000..4cf5cbe --- /dev/null +++ b/mknob.c @@ -0,0 +1,870 @@ +/* Copyright (c) 1997-1999 Miller Puckette. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* mknob.c written by Antoine Rousseau from g_vslider.c.*/ +/* g_7_guis.c written by Thomas Musil (c) IEM KUG Graz Austria 2000-2001 */ +/* thanks to Miller Puckette, Guenther Geiger and Krzystof Czaja */ + + +#include +#include +#include +#include +#include "m_pd.h" +#include "g_canvas.h" +#include "t_tk.h" +#include "g_all_guis.h" +#include + +#ifdef NT +#include +#else +#include +#endif + + +#define MKNOB_TANGLE 100 +#define MKNOB_DEFAULTH 100 +#define MKNOB_DEFAULTSIZE 25 +#define MKNOB_MINSIZE 12 +#define MKNOB_THICK 3 +/* ------------ mknob ----------------------- */ +typedef struct _mknob +{ + t_iemgui x_gui; + int x_pos; + int x_val; + int x_center; + int x_thick; + int x_lin0_log1; + int x_steady; + double x_min; + double x_max; + int x_H; + double x_k; +} t_mknob; + +t_widgetbehavior mknob_widgetbehavior; +static t_class *mknob_class; + +/* widget helper functions */ +static void mknob_update_knob(t_mknob *x, t_glist *glist) +{ + t_canvas *canvas=glist_getcanvas(glist); +// float val=(x->x_val + 50.0)/100.0/MKNOB_TANGLE; + float val=(x->x_val + 50.0)/100.0/x->x_H; + float angle, + radius=x->x_gui.x_w/2.0, + miniradius=MKNOB_THICK; + int x0,y0,x1,y1,xc,yc,xp,yp,xpc,ypc; + x0=text_xpix(&x->x_gui.x_obj, glist); + y0=text_ypix(&x->x_gui.x_obj, glist); + x1=x0+x->x_gui.x_w; + y1=y0+x->x_gui.x_w; + xc=(x0+x1)/2; + yc=(y0+y1)/2; + + if(x->x_gui.x_h<0) + angle=val*(M_PI*2)+M_PI/2.0; + else + angle=val*(M_PI*1.5)+3.0*M_PI/4.0; + + xp=xc+radius*cos(angle); + yp=yc+radius*sin(angle); + xpc=miniradius*cos(angle-M_PI/2); + ypc=miniradius*sin(angle-M_PI/2); + + sys_vgui(".x%x.c coords %xKNOB %d %d %d %d %d %d\n", + canvas,x,xp,yp,xc+xpc,yc+ypc,xc-xpc,yc-ypc); +} + +static void mknob_draw_update(t_mknob *x, t_glist *glist) +{ + if (glist_isvisible(glist)) + { + mknob_update_knob(x,glist); + + /*if(x->x_val == x->x_center) + { + if(!x->x_thick) + { + sys_vgui(".x%x.c itemconfigure %xKNOB -width 7\n", canvas, x); + x->x_thick = 1; + } + } + else + { + if(x->x_thick) + { + sys_vgui(".x%x.c itemconfigure %xKNOB -width 3\n", canvas, x); + x->x_thick = 0; + } + }*/ + } +} + +static void mknob_draw_new(t_mknob *x, t_glist *glist) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + int r = xpos + (x->x_val + 50)/100; + int xc=xpos+x->x_gui.x_w/2; + int yc=ypos+x->x_gui.x_w/2; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c create oval %d %d %d %d -fill #%6.6x -tags %xBASE\n", + canvas,xpos,ypos,xpos + x->x_gui.x_w, ypos + x->x_gui.x_w, + x->x_gui.x_bcol,x); + sys_vgui(".x%x.c create polygon %d %d %d %d %d %d -fill #%6.6x -tags %xKNOB\n", + glist_getcanvas(glist), + xc,ypos,xc-4,yc,xc+4,yc,x->x_gui.x_fcol,x); + mknob_update_knob(x,glist); + sys_vgui(".x%x.c create text %d %d -text {%s} -anchor w \ + -font {%s %d bold} -fill #%6.6x -tags %xLABEL\n", + canvas, xpos+x->x_gui.x_ldx, + ypos+x->x_gui.x_ldy, + strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:"", + x->x_gui.x_font, x->x_gui.x_fontsize, x->x_gui.x_lcol, x); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xOUT%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xIN%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1, x, 0);*/ +} + +static void mknob_draw_move(t_mknob *x, t_glist *glist) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + int r = xpos + (x->x_val + 50)/100; + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c coords %xBASE %d %d %d %d\n", + canvas, x, + xpos, ypos, + xpos + x->x_gui.x_w, ypos + x->x_gui.x_w); + mknob_update_knob(x,glist); + sys_vgui(".x%x.c coords %xLABEL %d %d\n", + canvas, x, xpos+x->x_gui.x_ldx, ypos+x->x_gui.x_ldy); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c coords %xOUT%d %d %d %d %d\n", + canvas, x, 0, + xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c coords %xIN%d %d %d %d %d\n", + canvas, x, 0, + xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1);*/ +} + +static void mknob_draw_erase(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c delete %xBASE\n", canvas, x); + sys_vgui(".x%x.c delete %xKNOB\n", canvas, x); + sys_vgui(".x%x.c delete %xLABEL\n", canvas, x); + /*if(!x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c delete %xOUT%d\n", canvas, x, 0); + if(!x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c delete %xIN%d\n", canvas, x, 0);*/ +} + +static void mknob_draw_config(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + sys_vgui(".x%x.c itemconfigure %xLABEL -font {%s %d bold} -fill #%6.6x -text {%s} \n", + canvas, x, x->x_gui.x_font, x->x_gui.x_fontsize, + x->x_gui.x_fsf.x_selected?IEM_GUI_COLOR_SELECTED:x->x_gui.x_lcol, + strcmp(x->x_gui.x_lab->s_name, "empty")?x->x_gui.x_lab->s_name:""); + sys_vgui(".x%x.c itemconfigure %xKNOB -fill #%6.6x\n", canvas, x, x->x_gui.x_fcol); + sys_vgui(".x%x.c itemconfigure %xBASE -fill #%6.6x\n", canvas, x, x->x_gui.x_bcol); +} + +static void mknob_draw_io(t_mknob* x,t_glist* glist, int old_snd_rcv_flags) +{ + int xpos=text_xpix(&x->x_gui.x_obj, glist); + int ypos=text_ypix(&x->x_gui.x_obj, glist); + t_canvas *canvas=glist_getcanvas(glist); + + /*if((old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && !x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xOUT%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos + x->x_gui.x_w-1, + xpos+ x->x_gui.x_w/2+4, ypos + x->x_gui.x_w, x, 0); + if(!(old_snd_rcv_flags & IEM_GUI_OLD_SND_FLAG) && x->x_gui.x_fsf.x_snd_able) + sys_vgui(".x%x.c delete %xOUT%d\n", canvas, x, 0); + if((old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && !x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c create rectangle %d %d %d %d -tags %xIN%d\n", + canvas, xpos+ x->x_gui.x_w/2-3, ypos, + xpos+ x->x_gui.x_w/2+4, ypos+1, x, 0); + if(!(old_snd_rcv_flags & IEM_GUI_OLD_RCV_FLAG) && x->x_gui.x_fsf.x_rcv_able) + sys_vgui(".x%x.c delete %xIN%d\n", canvas, x, 0);*/ +} + +static void mknob_draw_select(t_mknob* x,t_glist* glist) +{ + t_canvas *canvas=glist_getcanvas(glist); + + if(x->x_gui.x_fsf.x_selected) + { + //pd_bind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); + sys_vgui(".x%x.c itemconfigure %xBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + sys_vgui(".x%x.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, IEM_GUI_COLOR_SELECTED); + } + else + { + //pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym); + sys_vgui(".x%x.c itemconfigure %xBASE -outline #%6.6x\n", canvas, x, IEM_GUI_COLOR_NORMAL); + sys_vgui(".x%x.c itemconfigure %xLABEL -fill #%6.6x\n", canvas, x, x->x_gui.x_lcol); + } +} + +void mknob_draw(t_mknob *x, t_glist *glist, int mode) +{ + if(mode == IEM_GUI_DRAW_MODE_UPDATE) + mknob_draw_update(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_MOVE) + mknob_draw_move(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_NEW) + mknob_draw_new(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_SELECT) + mknob_draw_select(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_ERASE) + mknob_draw_erase(x, glist); + else if(mode == IEM_GUI_DRAW_MODE_CONFIG) + mknob_draw_config(x, glist); + /*else if(mode >= IEM_GUI_DRAW_MODE_IO) + mknob_draw_io(x, glist, mode - IEM_GUI_DRAW_MODE_IO);*/ +} + +/* ------------------------ mknob widgetbehaviour----------------------------- */ + + +static void mknob_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_mknob* x = (t_mknob*)z; + + *xp1 = text_xpix(&x->x_gui.x_obj, glist); + *yp1 = text_ypix(&x->x_gui.x_obj, glist); + *xp2 = *xp1 + x->x_gui.x_w; + *yp2 = *yp1 + x->x_gui.x_w; +} + +static void mknob_save(t_gobj *z, t_binbuf *b) +{ + t_mknob *x = (t_mknob *)z; + int bflcol[3], *ip1, *ip2; + t_symbol *srl[3]; + + iemgui_save(&x->x_gui, srl, bflcol); + ip1 = (int *)(&x->x_gui.x_isa); + ip2 = (int *)(&x->x_gui.x_fsf); + binbuf_addv(b, "ssiisiiffiisssiiiiiiiii", gensym("#X"),gensym("obj"), + (t_int)x->x_gui.x_obj.te_xpix, (t_int)x->x_gui.x_obj.te_ypix, + gensym("mknob"), x->x_gui.x_w, x->x_gui.x_h, + (float)x->x_min, (float)x->x_max, + x->x_lin0_log1, (*ip1)&IEM_INIT_ARGS_ALL, + srl[0], srl[1], srl[2], + x->x_gui.x_ldx, x->x_gui.x_ldy, + (*ip2)&IEM_FSTYLE_FLAGS_ALL, x->x_gui.x_fontsize, + bflcol[0], bflcol[1], bflcol[2], + x->x_val, x->x_steady); + binbuf_addv(b, ";"); +} + +void mknob_check_wh(t_mknob *x, int w, int h) +{ + int H; + + if(w < MKNOB_MINSIZE) w = MKNOB_MINSIZE; + x->x_gui.x_w = w; + + if(h < -1) h=-1; + if((h>0)&&(h<20)) h=20; + x->x_gui.x_h = h; + + H=x->x_gui.x_h; + if(H<0) H=360; + if(H==0) H=270; + x->x_H=H; + + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1); + + /*x->x_center = (x->x_gui.x_w-1)*50; + if(x->x_val > (x->x_gui.x_w*100 - 100)) + { + x->x_pos = x->x_gui.x_w*100 - 100; + x->x_val = x->x_pos; + } + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_gui.x_w - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 1);*/ +} + +void mknob_check_minmax(t_mknob *x, double min, double max) +{ + int H; + + if(x->x_lin0_log1) + { + if((min == 0.0)&&(max == 0.0)) + max = 1.0; + if(max > 0.0) + { + if(min <= 0.0) + min = 0.01*max; + } + else + { + if(min > 0.0) + max = 0.01*min; + } + } + x->x_min = min; + x->x_max = max; + if(x->x_min > x->x_max) /* bugfix */ + x->x_gui.x_isa.x_reverse = 1; + else + x->x_gui.x_isa.x_reverse = 0; + + if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(x->x_H - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(x->x_H - 1); + /*if(x->x_lin0_log1) + x->x_k = log(x->x_max/x->x_min)/(double)(MKNOB_TANGLE - 1); + else + x->x_k = (x->x_max - x->x_min)/(double)(MKNOB_TANGLE - 1);*/ +} + +static void mknob_properties(t_gobj *z, t_glist *owner) +{ + t_mknob *x = (t_mknob *)z; + char buf[800]; + t_symbol *srl[3]; + + iemgui_properties(&x->x_gui, srl); + sprintf(buf, "pdtk_iemgui_dialog %%s mknob \ + --------dimension(pix):-------- %d %d width: %d %d mouse: \ + -----------output-range:----------- %g left: %g right: %g \ + %d lin log %d %d empty %d \ + %s %s \ + %s %d %d \ + %d %d \ + %d %d %d\n", + x->x_gui.x_w, MKNOB_MINSIZE, x->x_gui.x_h, -1, + x->x_min, x->x_max, 0.0,/*no_schedule*/ + x->x_lin0_log1, x->x_gui.x_isa.x_loadinit, x->x_steady, -1,/*no multi, but iem-characteristic*/ + srl[0]->s_name, srl[1]->s_name, + srl[2]->s_name, x->x_gui.x_ldx, x->x_gui.x_ldy, + x->x_gui.x_fsf.x_font_style, x->x_gui.x_fontsize, + 0xffffff & x->x_gui.x_bcol, 0xffffff & x->x_gui.x_fcol, 0xffffff & x->x_gui.x_lcol); + gfxstub_new(&x->x_gui.x_obj.ob_pd, x, buf); +} + +static void mknob_set(t_mknob *x, t_floatarg f) /* bugfix */ +{ + double g; + + if(x->x_gui.x_isa.x_reverse) /* bugfix */ + { + if(f > x->x_min) + f = x->x_min; + if(f < x->x_max) + f = x->x_max; + } + else + { + if(f > x->x_max) + f = x->x_max; + if(f < x->x_min) + f = x->x_min; + } + if(x->x_lin0_log1) + g = log(f/x->x_min)/x->x_k; + else + g = (f - x->x_min) / x->x_k; + x->x_val = (int)(100.0*g + 0.49999); + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); +} + +static void mknob_bang(t_mknob *x) +{ + double out; + + if(x->x_lin0_log1) + out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01); + else + out = (double)(x->x_val)*0.01*x->x_k + x->x_min; + if((out < 1.0e-10)&&(out > -1.0e-10)) + out = 0.0; + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); +} + +static void mknob_dialog(t_mknob *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *srl[3]; + int w = (int)atom_getintarg(0, argc, argv); + int h = (int)atom_getintarg(1, argc, argv); + double min = (double)atom_getfloatarg(2, argc, argv); + double max = (double)atom_getfloatarg(3, argc, argv); + int lilo = (int)atom_getintarg(4, argc, argv); + int steady = (int)atom_getintarg(17, argc, argv); + int sr_flags; + + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady) + x->x_steady = 1; + else + x->x_steady = 0; + sr_flags = iemgui_dialog(&x->x_gui, srl, argc, argv); + //x->x_gui.x_h = iemgui_clip_size(h); + //x->x_gui.x_w = iemgui_clip_size(w); + mknob_check_wh(x, w, h); + mknob_check_minmax(x, min, max); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_CONFIG); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_IO + sr_flags); + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x); +} + +static int xm0,ym0,xm,ym; + +static void mknob_motion(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int old = x->x_val; + float d=-dy; + + if (abs(dx)>abs(dy)) d=dx; + + if(x->x_gui.x_fsf.x_finemoved) + x->x_pos += (int)d; + else + x->x_pos += 100*(int)d; + x->x_val = x->x_pos; + if(x->x_val > (100*x->x_H - 100)) + { + x->x_val = 100*x->x_H - 100; + x->x_pos += 50; + x->x_pos -= x->x_pos%100; + } + if(x->x_val < 0) + { + x->x_val = 0; + x->x_pos -= 50; + x->x_pos -= x->x_pos%100; + } + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_motion_circular(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int old = x->x_val; + float alpha; + + xm+=dx; + ym+=dy; + + alpha=atan2(xm-xc,ym-yc)*180.0/M_PI; + + x->x_pos=(int)(31500-alpha*100.0)%36000; + if(x->x_pos>31500) x->x_pos=0; + else if(x->x_pos>(27000-100)) x->x_pos=(27000-100); + + x->x_val=x->x_pos; + + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_motion_fullcircular(t_mknob *x, t_floatarg dx, t_floatarg dy) +{ + int xc=text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int yc=text_ypix(&x->x_gui.x_obj, x->x_gui.x_glist)+x->x_gui.x_w/2; + int old = x->x_val; + float alpha; + + xm+=dx; + ym+=dy; + + alpha=atan2(xm-xc,ym-yc)*180.0/M_PI; + + x->x_pos=(int)(36000-alpha*100.0)%36000; + /*if(x->x_pos>31500) x->x_pos=0; + else if(x->x_pos>(27000-100)) x->x_pos=(27000-100);*/ + + if(x->x_pos>(36000-100)) x->x_pos=(36000-100); + x->x_val=x->x_pos; + + if(old != x->x_val) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +static void mknob_click(t_mknob *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + xm0=xm=xpos; + ym0=ym=ypos; + //if(!x->x_steady) + //x->x_val = (int)(100.0 * (xpos - text_xpix(&x->x_gui.x_obj, x->x_gui.x_glist))); + if(x->x_val > (100*x->x_H - 100)) + x->x_val = 100*x->x_H - 100; + if(x->x_val < 0) + x->x_val = 0; + x->x_pos = x->x_val; + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + + if(x->x_gui.x_h<0) + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion_fullcircular, 0, xpos, ypos); + else if(x->x_gui.x_h==0) + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion_circular, 0, xpos, ypos); + else + glist_grab(x->x_gui.x_glist, &x->x_gui.x_obj.te_g, + (t_glistmotionfn)mknob_motion, 0, xpos, ypos); + +} + +static int mknob_newclick(t_gobj *z, struct _glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, int doit) +{ + t_mknob* x = (t_mknob *)z; + + if(doit) + { + mknob_click( x, (t_floatarg)xpix, (t_floatarg)ypix, (t_floatarg)shift, + 0, (t_floatarg)alt); + if(shift) + x->x_gui.x_fsf.x_finemoved = 1; + else + x->x_gui.x_fsf.x_finemoved = 0; + } + return (1); +} + +static void mknob_size(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + int w=(int)atom_getintarg(0, ac, av), + h=x->x_gui.x_h; + + if(ac > 1) h=(int)atom_getintarg(1, ac, av); + + mknob_check_wh(x, w, h); + iemgui_size((void *)x, &x->x_gui); +} + +static void mknob_delta(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_delta((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_pos((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_range(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + mknob_check_minmax(x, (double)atom_getfloatarg(0, ac, av), + (double)atom_getfloatarg(1, ac, av)); +} + +static void mknob_color(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_color((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_send(t_mknob *x, t_symbol *s) +{iemgui_send(x, &x->x_gui, s);} + +static void mknob_receive(t_mknob *x, t_symbol *s) +{iemgui_receive(x, &x->x_gui, s);} + +static void mknob_label(t_mknob *x, t_symbol *s) +{iemgui_label((void *)x, &x->x_gui, s);} + +static void mknob_label_pos(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_pos((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_label_font(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{iemgui_label_font((void *)x, &x->x_gui, s, ac, av);} + +static void mknob_log(t_mknob *x) +{ + x->x_lin0_log1 = 1; + mknob_check_minmax(x, x->x_min, x->x_max); +} + +static void mknob_lin(t_mknob *x) +{ + x->x_lin0_log1 = 0; + x->x_k = (x->x_max - x->x_min)/(double)(x->x_gui.x_w - 1); +} + +static void mknob_init(t_mknob *x, t_floatarg f) +{ + x->x_gui.x_isa.x_loadinit = (f==0.0)?0:1; +} + +static void mknob_steady(t_mknob *x, t_floatarg f) +{ + x->x_steady = (f==0.0)?0:1; +} + +static void mknob_float(t_mknob *x, t_floatarg f) +{ + double out; + + mknob_set(x, f); + if(x->x_lin0_log1) + out = x->x_min*exp(x->x_k*(double)(x->x_val)*0.01); + else + out = (double)(x->x_val)*0.01*x->x_k + x->x_min; + if((out < 1.0e-10)&&(out > -1.0e-10)) + out = 0.0; + if(x->x_gui.x_fsf.x_put_in2out) + { + outlet_float(x->x_gui.x_obj.ob_outlet, out); + if(x->x_gui.x_fsf.x_snd_able && x->x_gui.x_snd->s_thing) + pd_float(x->x_gui.x_snd->s_thing, out); + } +} + +static void mknob_loadbang(t_mknob *x) +{ + if(!sys_noloadbang && x->x_gui.x_isa.x_loadinit) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_UPDATE); + mknob_bang(x); + } +} + +/*static void mknob_list(t_mknob *x, t_symbol *s, int ac, t_atom *av) +{ + int l=iemgui_list((void *)x, &x->x_gui, s, ac, av); + + if(l < 0) + { + if(IS_A_FLOAT(av,0)) + mknob_float(x, atom_getfloatarg(0, ac, av)); + } + else if(l > 0) + { + (*x->x_gui.x_draw)(x, x->x_gui.x_glist, IEM_GUI_DRAW_MODE_MOVE); + canvas_fixlinesfor(glist_getcanvas(x->x_gui.x_glist), (t_text*)x); + } +}*/ + +static void *mknob_new(t_symbol *s, int argc, t_atom *argv) +{ + t_mknob *x = (t_mknob *)pd_new(mknob_class); + int bflcol[]={-262144, -1, -1}; + //t_symbol *srl[3]; + int w=MKNOB_DEFAULTSIZE, h=MKNOB_DEFAULTH; + int fs=8 ,lilo=0, ldx=-2, ldy=-6, f=0, v=0, steady=1; + //int iinit=0, ifstyle=0; + double min=0.0, max=(double)(IEM_SL_DEFAULTSIZE-1); + //t_iem_init_symargs *init=(t_iem_init_symargs *)(&iinit); + //t_iem_fstyle_flags *fstyle=(t_iem_fstyle_flags *)(&ifstyle); + char str[144]; + + /*srl[0] = gensym("empty"); + srl[1] = gensym("empty"); + srl[2] = gensym("empty");*/ + + if(((argc == 17)||(argc == 18))&&IS_A_FLOAT(argv,0)&&IS_A_FLOAT(argv,1) + &&IS_A_FLOAT(argv,2)&&IS_A_FLOAT(argv,3) + &&IS_A_FLOAT(argv,4)&&IS_A_FLOAT(argv,5) + &&(IS_A_SYMBOL(argv,6)||IS_A_FLOAT(argv,6)) + &&(IS_A_SYMBOL(argv,7)||IS_A_FLOAT(argv,7)) + &&(IS_A_SYMBOL(argv,8)||IS_A_FLOAT(argv,8)) + &&IS_A_FLOAT(argv,9)&&IS_A_FLOAT(argv,10) + &&IS_A_FLOAT(argv,11)&&IS_A_FLOAT(argv,12)&&IS_A_FLOAT(argv,13) + &&IS_A_FLOAT(argv,14)&&IS_A_FLOAT(argv,15)&&IS_A_FLOAT(argv,16)) + { + w = (int)atom_getintarg(0, argc, argv); + h = (int)atom_getintarg(1, argc, argv); + min = (double)atom_getfloatarg(2, argc, argv); + max = (double)atom_getfloatarg(3, argc, argv); + lilo = (int)atom_getintarg(4, argc, argv); + iem_inttosymargs(&x->x_gui.x_isa, atom_getintarg(5, argc, argv)); + iemgui_new_getnames(&x->x_gui, 6, argv); + ldx = (int)atom_getintarg(9, argc, argv); + ldy = (int)atom_getintarg(10, argc, argv); + iem_inttofstyle(&x->x_gui.x_fsf, atom_getintarg(11, argc, argv)); + fs = (int)atom_getintarg(12, argc, argv); + bflcol[0] = (int)atom_getintarg(13, argc, argv); + bflcol[1] = (int)atom_getintarg(14, argc, argv); + bflcol[2] = (int)atom_getintarg(15, argc, argv); + v = (int)atom_getintarg(16, argc, argv); + /*iinit = (int)atom_getintarg(5, argc, argv); + if(IS_A_SYMBOL(argv,6)) + srl[0] = atom_getsymbolarg(6, argc, argv); + else if(IS_A_FLOAT(argv,6)) + { + sprintf(str, "%d", (int)atom_getintarg(6, argc, argv)); + srl[0] = gensym(str); + } + if(IS_A_SYMBOL(argv,7)) + srl[1] = atom_getsymbolarg(7, argc, argv); + else if(IS_A_FLOAT(argv,7)) + { + sprintf(str, "%d", (int)atom_getintarg(7, argc, argv)); + srl[1] = gensym(str); + } + if(IS_A_SYMBOL(argv,8)) + srl[2] = atom_getsymbolarg(8, argc, argv); + else if(IS_A_FLOAT(argv,8)) + { + sprintf(str, "%d", (int)atom_getintarg(8, argc, argv)); + srl[2] = gensym(str); + }*/ + //ifstyle = (int)atom_getintarg(11, argc, argv); + } + else iemgui_new_getnames(&x->x_gui, 6, 0); + + if((argc == 18)&&IS_A_FLOAT(argv,17)) + steady = (int)atom_getintarg(17, argc, argv); + + /*iinit &= IEM_INIT_ARGS_ALL; + ifstyle &= IEM_FSTYLE_FLAGS_ALL; + fstyle->x_snd_able = 1; + fstyle->x_rcv_able = 1;*/ + x->x_gui.x_draw = (t_iemfunptr)mknob_draw; + x->x_gui.x_fsf.x_snd_able = 1; + x->x_gui.x_fsf.x_rcv_able = 1; + x->x_gui.x_glist = (t_glist *)canvas_getcurrent(); + //x->x_gui.x_isa = *init; + if(x->x_gui.x_isa.x_loadinit) + x->x_val = v; + else + x->x_val = 0; + x->x_pos = x->x_val; + if(lilo != 0) lilo = 1; + x->x_lin0_log1 = lilo; + if(steady != 0) steady = 1; + x->x_steady = steady; + if(!strcmp(x->x_gui.x_snd->s_name, "empty")) x->x_gui.x_fsf.x_snd_able = 0; + if(!strcmp(x->x_gui.x_rcv->s_name, "empty")) x->x_gui.x_fsf.x_rcv_able = 0; + //if(!strcmp(srl[0]->s_name, "empty")) fstyle->x_snd_able = 0; + //if(!strcmp(srl[1]->s_name, "empty")) fstyle->x_rcv_able = 0; + //x->x_gui.x_unique_num = 0; + if(x->x_gui.x_fsf.x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(x->x_gui.x_fsf.x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { x->x_gui.x_fsf.x_font_style = 0; + /*if(fstyle->x_font_style == 1) strcpy(x->x_gui.x_font, "helvetica"); + else if(fstyle->x_font_style == 2) strcpy(x->x_gui.x_font, "times"); + else { fstyle->x_font_style = 0;*/ + strcpy(x->x_gui.x_font, "courier"); } + //x->x_gui.x_fsf = *fstyle; + //iemgui_first_dollararg2sym(&x->x_gui, srl); + //if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, srl[1]); + /*x->x_gui.x_snd = srl[0]; + x->x_gui.x_rcv = srl[1]; + x->x_gui.x_lab = srl[2];*/ + if(x->x_gui.x_fsf.x_rcv_able) pd_bind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + x->x_gui.x_ldx = ldx; + x->x_gui.x_ldy = ldy; + if(fs < 4) + fs = 4; + x->x_gui.x_fontsize = fs; + //x->x_gui.x_h = iemgui_clip_size(h); + //x->x_gui.x_w = iemgui_clip_size(w); + mknob_check_wh(x, w, h); + //mknob_check_width(x, w); + mknob_check_minmax(x, min, max); + iemgui_all_colfromload(&x->x_gui, bflcol); + x->x_thick = 0; + iemgui_verify_snd_ne_rcv(&x->x_gui); + outlet_new(&x->x_gui.x_obj, &s_float); + return (x); +} + +static void mknob_free(t_mknob *x) +{ + /*if(x->x_gui.x_fsf.x_selected) + pd_unbind(&x->x_gui.x_obj.ob_pd, iemgui_key_sym);*/ + if(x->x_gui.x_fsf.x_rcv_able) + pd_unbind(&x->x_gui.x_obj.ob_pd, x->x_gui.x_rcv); + gfxstub_deleteforkey(x); +} + +extern void canvas_iemguis(t_glist *gl, t_symbol *guiobjname); + +void canvas_mknob(t_glist *gl, t_symbol *s, int argc, t_atom *argv) +{ + canvas_iemguis(gl, gensym("mknob")); +} + +void mknob_setup(void) +{ + mknob_class = class_new(gensym("mknob"), (t_newmethod)mknob_new, + (t_method)mknob_free, sizeof(t_mknob), 0, A_GIMME, 0); +#ifndef GGEE_mknob_COMPATIBLE +// class_addcreator((t_newmethod)mknob_new, gensym("mknob"), A_GIMME, 0); +#endif + class_addbang(mknob_class,mknob_bang); + class_addfloat(mknob_class,mknob_float); + //class_addlist(mknob_class, mknob_list); + class_addmethod(mknob_class, (t_method)mknob_click, gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_motion, gensym("motion"), + A_FLOAT, A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_dialog, gensym("dialog"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_loadbang, gensym("loadbang"), 0); + class_addmethod(mknob_class, (t_method)mknob_set, gensym("set"), A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_size, gensym("size"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_delta, gensym("delta"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_pos, gensym("pos"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_range, gensym("range"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_color, gensym("color"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_send, gensym("send"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_receive, gensym("receive"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_label, gensym("label"), A_DEFSYM, 0); + class_addmethod(mknob_class, (t_method)mknob_label_pos, gensym("label_pos"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_label_font, gensym("label_font"), A_GIMME, 0); + class_addmethod(mknob_class, (t_method)mknob_log, gensym("log"), 0); + class_addmethod(mknob_class, (t_method)mknob_lin, gensym("lin"), 0); + class_addmethod(mknob_class, (t_method)mknob_init, gensym("init"), A_FLOAT, 0); + class_addmethod(mknob_class, (t_method)mknob_steady, gensym("steady"), A_FLOAT, 0); + /*if(!iemgui_key_sym) + iemgui_key_sym = gensym("#keyname");*/ + mknob_widgetbehavior.w_getrectfn = mknob_getrect; + mknob_widgetbehavior.w_displacefn = iemgui_displace; + mknob_widgetbehavior.w_selectfn = iemgui_select; + mknob_widgetbehavior.w_activatefn = NULL; + mknob_widgetbehavior.w_deletefn = iemgui_delete; + mknob_widgetbehavior.w_visfn = iemgui_vis; + mknob_widgetbehavior.w_clickfn = mknob_newclick; + //mknob_widgetbehavior.w_propertiesfn = mknob_properties; + //mknob_widgetbehavior.w_savefn = mknob_save; + class_setwidget(mknob_class, &mknob_widgetbehavior); + + class_setsavefn(mknob_class, mknob_save); + class_setpropertiesfn(mknob_class, mknob_properties); + class_addmethod(canvas_class, (t_method)canvas_mknob, gensym("mknob"), + A_GIMME, A_NULL); +} diff --git a/panvol~.c b/panvol~.c new file mode 100644 index 0000000..2e302c6 --- /dev/null +++ b/panvol~.c @@ -0,0 +1,119 @@ +/*************************************************************************** + * File: pan~.c + * Auth: Iain Mott [iain.mott@bigpond.com] + * Maintainer: Iain Mott [iain.mott@bigpond.com] + * Version: Part of motex_1.1.2 + * Date: January 2001 + * + * Description: Pd signal external. Equal-power stereo panning + * Angle input specified in degrees. -45 left, 0 centre, 45 right. + * See supporting Pd patch: pan~.pd + * + * Copyright (C) 2001 by Iain Mott [iain.mott@bigpond.com] + * + * 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, or (at your option) + * any later version. + * + * 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, which should be included with this + * program, for more details. + * + ****************************************************************************/ + +/* I've only add a global volume... Antoine Rousseau 2003*/ + +#include "m_pd.h" +#include + +static t_class *pan_class; +#define RADCONST 0.017453293 +#define ROOT2DIV2 0.707106781 + +typedef struct _pan +{ + t_object x_obj; + float x_f; + float pan; + float left; + float right; + float vol; +} t_pan; + +static void *pan_new(t_symbol *s, int argc, t_atom *argv) +{ + t_pan *x = (t_pan *)pd_new(pan_class); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("panf")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("volf")); + + x->x_f = 0; + x->left = ROOT2DIV2; + x->right = ROOT2DIV2; + x->vol = 1; + return (x); +} + +static t_int *pan_perform(t_int *w) +{ + float *in1 = (t_float *)(w[1]); + float *out1 = (t_float *)(w[2]); + float *out2 = (t_float *)(w[3]); + int n = (int)(w[4]); + t_pan *x = (t_pan *)(w[5]); + float left=x->left*x->vol; + float right=x->right*x->vol; + float value; + + while (n--) + { + value = *in1++; + *out1++ = value * left; + *out2++ = value * right; + } + return (w+6); +} + +static void pan_dsp(t_pan *x, t_signal **sp) +{ + int n = sp[0]->s_n; + float *in1 = sp[0]->s_vec; + float *out1 = sp[1]->s_vec; + float *out2 = sp[2]->s_vec; + + dsp_add(pan_perform, 5, + in1, out1, out2, n, x); +} + +static void pan_f(t_pan *x, t_floatarg f) +{ + double angle; + f = f < -45 ? -45 : f; + f = f > 45 ? 45 : f; + angle = f * RADCONST; // convert degrees to radians + x->right = ROOT2DIV2 * (cos(angle) + sin(angle)); + x->left = ROOT2DIV2 * (cos(angle) - sin(angle)); +/* post("left = %f : right = %f", x->left, x->right); */ +} + +static void vol_f(t_pan *x, t_floatarg f) +{ + f = f < 0 ? 0 : f; + x->vol=f; +} + +void panvol_tilde_setup(void) +{ + pan_class = class_new(gensym("panvol~"), (t_newmethod)pan_new, 0, + sizeof(t_pan), 0, A_GIMME, 0); + + class_addmethod(pan_class, nullfn, gensym("signal"), 0); + + class_addmethod(pan_class, (t_method)pan_dsp, gensym("dsp"), 0); + class_addmethod(pan_class, (t_method)pan_f, gensym("panf"), A_FLOAT, 0); + class_addmethod(pan_class, (t_method)vol_f, gensym("volf"), A_FLOAT, 0); +} diff --git a/popen.c b/popen.c new file mode 100644 index 0000000..c97a17c --- /dev/null +++ b/popen.c @@ -0,0 +1,211 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "s_stuff.h" +#include +#include +#include +#include +#define BUFSIZE 4096 + +typedef struct popen +{ + t_object x_obj; + FILE *x_file; + char x_data[BUFSIZE]; + int x_count; + int x_ropened; + t_outlet *x_msgout; +} t_popen; + +t_class *popen_class; +static t_binbuf *inbinbuf; + + +static void *popen_new(t_symbol *s, int argc, t_atom *argv) +{ + t_popen *x; + + x = (t_popen *)pd_new(popen_class); + + x->x_file = NULL; + x->x_count=0; + x->x_msgout = outlet_new(&x->x_obj, &s_anything); + x->x_ropened=0; + return (x); +} + +static void popen_close(t_popen *x) +{ + if(x->x_ropened) { + sys_rmpollfn(fileno(x->x_file)); + //fflush(x->x_file); + } + if(x->x_file) pclose(x->x_file); + x->x_file=0; + x->x_ropened=0; +} + +static void popen_ff(t_popen *x) +{ + +} + +static void popen_open(t_popen *x, t_symbol *s,int argc, t_atom *argv) +{ + char cmd[512],*text; + int cmd_len; + + t_binbuf *bb=binbuf_new(); + + popen_close(x); + + //post("argc=%d",argc); + //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name); + + binbuf_add(bb,argc,argv); + binbuf_gettext(bb, &text,&cmd_len); + binbuf_free(bb); + + strncpy(cmd,text,cmd_len); + cmd[cmd_len]=0; + //post("cmd=%s",cmd); + + x->x_file=popen(cmd,"w"); + +} + +static void popen_list(t_popen *x, t_symbol *s, + int argc, t_atom *argv) +{ + t_binbuf *bb; + char *buf; + int l; + + if(!x->x_file) return; + + bb=binbuf_new(); + binbuf_add(bb,argc,argv); + //binbuf_print(bb); + binbuf_gettext(bb, &buf,&l); + buf[l]=0; + + //printf("popen list: %s\n",buf); + fprintf(x->x_file,"%s\n",buf);fflush(x->x_file); + + freebytes(buf,l); + binbuf_free(bb); +} + +static void popen_out(t_popen *x, t_binbuf *b) +{ + t_atom messbuf[1024]; + int msg, natom = binbuf_getnatom(b); + t_atom *at = binbuf_getvec(b); + for (msg = 0; msg < natom;) + { + int emsg; + for (emsg = msg; emsg < natom && at[emsg].a_type != A_COMMA + && at[emsg].a_type != A_SEMI; emsg++) + ; + if (emsg > msg) + { + int i; + for (i = msg; i < emsg; i++) + if (at[i].a_type == A_DOLLAR || at[i].a_type == A_DOLLSYM) + { + pd_error(x, "popen: got dollar sign in message"); + goto nodice; + } + if (at[msg].a_type == A_FLOAT) + { + if (emsg > msg + 1) + outlet_list(x->x_msgout, 0, emsg-msg, at + msg); + else outlet_float(x->x_msgout, at[msg].a_w.w_float); + } + else if (at[msg].a_type == A_SYMBOL) + outlet_anything(x->x_msgout, at[msg].a_w.w_symbol, + emsg-msg-1, at + msg + 1); + } + nodice: + msg = emsg + 1; + } +} + +static void popen_read(t_popen *x,int fd) +{ + int len,i=0; + unsigned char b; + unsigned char buffer[BUFSIZE]; + + if((len=read(fd,buffer,BUFSIZE))> 0){ + + for(i=0;ix_count>=BUFSIZE) x->x_count=0; + x->x_data[x->x_count++]=buffer[i]; + if(buffer[i]==';') { + binbuf_text(inbinbuf, x->x_data, x->x_count); + x->x_count=0; + popen_out(x,inbinbuf); + } + } + } +} + +static void popen_ropen(t_popen *x, t_symbol *s,int argc, t_atom *argv) +{ + char cmd[512],*text; + int cmd_len; + + t_binbuf *bb=binbuf_new(); + + popen_close(x); + + //post("argc=%d",argc); + //post("argv[0]=%s",atom_getsymbol(&argv[0])->s_name); + + binbuf_add(bb,argc,argv); + binbuf_gettext(bb, &text,&cmd_len); + binbuf_free(bb); + + strncpy(cmd,text,cmd_len); + cmd[cmd_len]=0; + //post("cmd=%s",cmd); + + x->x_file=popen(cmd,"r"); + sys_addpollfn(fileno(x->x_file),(t_fdpollfn)popen_read,(void*)x); + x->x_ropened=1; +} + +void popen_setup(void ) +{ + inbinbuf = binbuf_new(); + popen_class = class_new(gensym("popen"), (t_newmethod)popen_new, + (t_method)popen_close,sizeof(t_popen), 0, A_GIMME, 0); + class_addmethod(popen_class, (t_method)popen_close, + gensym("close"), 0); + class_addmethod(popen_class, (t_method)popen_open, + gensym("open"), A_GIMME, 0); + class_addmethod(popen_class, (t_method)popen_ropen, + gensym("ropen"), A_GIMME, 0); + class_addlist(popen_class, popen_list); + +} + diff --git a/readsfv~.c b/readsfv~.c new file mode 100644 index 0000000..6707cf1 --- /dev/null +++ b/readsfv~.c @@ -0,0 +1,1683 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* this file contains, first, a collection of soundfile access routines, a +sort of soundfile library. Second, the "soundfiler" object is defined which +uses the routines to read or write soundfiles, synchronously, from garrays. +These operations are not to be done in "real time" as they may have to wait +for disk accesses (even the write routine.) Finally, the realtime objects +readsf~ and writesf~ are defined which confine disk operations to a separate +thread so that they can be used in real time. The real-time disk access +objects are available for linux only so far, although they could be compiled +for Windows if someone were willing to find a Pthreads package for it. */ + +/* this is a partial copy of d_soundfile, with some hacking: + 1: a fix in soundfiler to compute the normalization factor only on + the samples we want to write on the disk... + 2: a version of readsf~ that works with a (positive) speed parameter. + + Antoine Rousseau +*/ + +#ifdef UNIX +#include +#include +#endif +#include +#ifdef NT +#include +#endif +#include +#include +#include + +#include "m_pd.h" + +#define MAXSFCHANS 4 + + +/***************** soundfile header structures ************************/ + +typedef unsigned short uint16; +typedef unsigned long uint32; + +#define FORMAT_WAVE 0 +#define FORMAT_AIFF 1 +#define FORMAT_NEXT 2 + +/* the NeXTStep sound header structure; can be big or little endian */ + +typedef struct _nextstep +{ + char ns_fileid[4]; /* magic number '.snd' if file is big-endian */ + uint32 ns_onset; /* byte offset of first sample */ + uint32 ns_length; /* length of sound in bytes */ + uint32 ns_format; /* format; see below */ + uint32 ns_sr; /* sample rate */ + uint32 ns_nchans; /* number of channels */ + char ns_info[4]; /* comment */ +} t_nextstep; + +#define NS_FORMAT_LINEAR_16 3 +#define NS_FORMAT_LINEAR_24 4 +#define NS_FORMAT_FLOAT 6 +#define SCALE (1./(1024. * 1024. * 1024. * 2.)) + +/* the WAVE header. All Wave files are little endian. We assume + the "fmt" chunk comes first which is usually the case but perhaps not + always; same for AIFF and the "COMM" chunk. */ + +typedef unsigned word; +typedef unsigned long dword; + +typedef struct _wave +{ + char w_fileid[4]; /* chunk id 'RIFF' */ + uint32 w_chunksize; /* chunk size */ + char w_waveid[4]; /* wave chunk id 'WAVE' */ + char w_fmtid[4]; /* format chunk id 'fmt ' */ + uint32 w_fmtchunksize; /* format chunk size */ + uint16 w_fmttag; /* format tag, 1 for PCM */ + uint16 w_nchannels; /* number of channels */ + uint32 w_samplespersec; /* sample rate in hz */ + uint32 w_navgbytespersec; /* average bytes per second */ + uint16 w_nblockalign; /* number of bytes per sample */ + uint16 w_nbitspersample; /* number of bits in a sample */ + char w_datachunkid[4]; /* data chunk id 'data' */ + uint32 w_datachunksize; /* length of data chunk */ +} t_wave; + +typedef struct _fmt /* format chunk */ +{ + uint16 f_fmttag; /* format tag, 1 for PCM */ + uint16 f_nchannels; /* number of channels */ + uint32 f_samplespersec; /* sample rate in hz */ + uint32 f_navgbytespersec; /* average bytes per second */ + uint16 f_nblockalign; /* number of bytes per frame */ + uint16 f_nbitspersample; /* number of bits in a sample */ +} t_fmt; + +typedef struct _wavechunk /* ... and the last two items */ +{ + char wc_id[4]; /* data chunk id, e.g., 'data' or 'fmt ' */ + uint32 wc_size; /* length of data chunk */ +} t_wavechunk; + +/* the AIFF header. I'm assuming AIFC is compatible but don't really know + that. */ + +typedef struct _datachunk +{ + char dc_id[4]; /* data chunk id 'SSND' */ + uint32 dc_size; /* length of data chunk */ +} t_datachunk; + +//#define CHUNKHDRSIZE sizeof(t_datachunk) + +typedef struct _comm +{ + uint16 c_nchannels; /* number of channels */ + uint16 c_nframeshi; /* # of sample frames (hi) */ + uint16 c_nframeslo; /* # of sample frames (lo) */ + uint16 c_bitspersamp; /* bits per sample */ + unsigned char c_samprate[10]; /* sample rate, 80-bit float! */ +} t_comm; + + /* this version is more convenient for writing them out: */ +typedef struct _aiff +{ + char a_fileid[4]; /* chunk id 'FORM' */ + uint32 a_chunksize; /* chunk size */ + char a_aiffid[4]; /* aiff chunk id 'AIFF' */ + char a_fmtid[4]; /* format chunk id 'COMM' */ + uint32 a_fmtchunksize; /* format chunk size, 18 */ + uint16 a_nchannels; /* number of channels */ + uint16 a_nframeshi; /* # of sample frames (hi) */ + uint16 a_nframeslo; /* # of sample frames (lo) */ + uint16 a_bitspersamp; /* bits per sample */ + unsigned char a_samprate[10]; /* sample rate, 80-bit float! */ +} t_aiff; + +#define AIFFHDRSIZE 38 /* probably not what sizeof() gives */ + + +#define AIFFPLUS (AIFFHDRSIZE + 8) /* header size including first chunk hdr */ + +#define WHDR1 sizeof(t_nextstep) +#define WHDR2 (sizeof(t_wave) > WHDR1 ? sizeof (t_wave) : WHDR1) +#define WRITEHDRSIZE (AIFFPLUS > WHDR2 ? AIFFPLUS : WHDR2) + +#define READHDRSIZE (16 > WHDR2 ? 16 : WHDR2) + +#define OBUFSIZE MAXPDSTRING /* assume MAXPDSTRING is bigger than headers */ + +#ifdef NT +#include +#define BINCREATE _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC | +#else +#define BINCREATE O_WRONLY|O_CREAT|O_TRUNC +#endif + +/* this routine returns 1 if the high order byte comes at the lower +address on our architecture (big-endianness.). It's 1 for Motorola, +0 for Intel: */ + +extern int garray_ambigendian(void); + +/* byte swappers */ + +static uint32 swap4(uint32 n, int doit) +{ + if (doit) + return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | + ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); + else return (n); +} + +static uint16 swap2(uint32 n, int doit) +{ + if (doit) + return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); + else return (n); +} + +static void swapstring(char *foo, int doit) +{ + if (doit) + { + char a = foo[0], b = foo[1], c = foo[2], d = foo[3]; + foo[0] = d; foo[1] = c; foo[2] = b; foo[3] = a; + } +} + +/******************** soundfile access routines **********************/ + +void readsf_banana( void); /* debugging */ + +/* This routine opens a file, looks for either a nextstep or "wave" header, +* seeks to end of it, and fills in bytes per sample and number of channels. +* Only 2- and 3-byte fixed-point samples and 4-byte floating point samples +* are supported. If "headersize" is nonzero, the +* caller should supply the number of channels, endinanness, and bytes per +* sample; the header is ignored. Otherwise, the routine tries to read the +* header and fill in the properties. +*/ + +extern int open_soundfile(const char *dirname, const char *filename, int headersize, + int *p_bytespersamp, int *p_bigendian, int *p_nchannels, long *p_bytelimit, + long skipframes); + + +static void soundfile_xferin(int sfchannels, int nvecs, float **vecs, + long itemsread, unsigned char *buf, int nitems, int bytespersamp, + int bigendian) +{ + int i, j; + unsigned char *sp, *sp2; + float *fp; + int nchannels = (sfchannels < nvecs ? sfchannels : nvecs); + int bytesperframe = bytespersamp * sfchannels; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[1] << 24) | (sp2[0] << 16)); + } + } + else if (bytespersamp == 3) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8)); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *fp = SCALE * ((sp2[2] << 24) | (sp2[1] << 16) + | (sp2[0] << 8)); + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[0] << 24) | (sp2[1] << 16) + | (sp2[2] << 8) | sp2[3]); + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + itemsread; + j < nitems; j++, sp2 += bytesperframe, fp++) + *(long *)fp = ((sp2[3] << 24) | (sp2[2] << 16) + | (sp2[1] << 8) | sp2[0]); + } + } + } + /* zero out other outputs */ + for (i = sfchannels; i < nvecs; i++) + for (j = nitems, fp = vecs[i]; j--; ) + *fp++ = 0; + +} + +static void interpolate(int nvec,float **invec,int nin, + float **outvec,int nout) +{ + + float r=nin/(float)nout; + int i,j; + + + for(i=0;i + -skip + -bytes + -normalize + -nextstep + -wave + -big + -little + */ + + /* the routine which actually does the work should LATER also be called + from garray_write16. */ + + + /* Parse arguments for writing. The "obj" argument is only for flagging + errors. For streaming to a file the "normalize", "onset" and "nframes" + arguments shouldn't be set but the calling routine flags this. */ + +static int soundfiler2_writeargparse(void *obj, int *p_argc, t_atom **p_argv, + t_symbol **p_filesym, + int *p_filetype, int *p_bytespersamp, int *p_swap, int *p_bigendian, + int *p_normalize, long *p_onset, long *p_nframes,float *p_amp) +{ + int argc = *p_argc; + t_atom *argv = *p_argv; + int bytespersamp = 2, bigendian = 0, + endianness = -1, swap, filetype = FORMAT_WAVE, normalize = 0; + long onset = 0, nframes = 0x7fffffff; + float amp=1; + t_symbol *filesym; + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((onset = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "nframes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((nframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "bytes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((bytespersamp = argv[1].a_w.w_float) < 2) || + bytespersamp > 4) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "normalize")) + { + normalize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "amp")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT) + goto usage; + amp = argv[1].a_w.w_float; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "wave")) + { + filetype = FORMAT_WAVE; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "nextstep")) + { + filetype = FORMAT_NEXT; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "aiff")) + { + filetype = FORMAT_AIFF; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "big")) + { + endianness = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "little")) + { + endianness = 1; + argc -= 1; argv += 1; + } + else goto usage; + } + /* only NextStep handles floating point samples */ + if (bytespersamp == 4) + filetype = FORMAT_NEXT; + + /* for WAVE force little endian; for nextstep use machine native */ + if (filetype == FORMAT_WAVE) + { + bigendian = 0; + if (endianness == 1) + pd_error(obj, "WAVE file forced to little endian"); + } + else if (filetype == FORMAT_AIFF) + { + bigendian = 1; + if (endianness == 0) + pd_error(obj, "AIFF file forced to big endian"); + } + else if (endianness == -1) + { + bigendian = garray_ambigendian(); + } + swap = (bigendian != garray_ambigendian()); + if (!argc || argv->a_type != A_SYMBOL) + goto usage; + filesym = argv->a_w.w_symbol; + argc--; argv++; + + *p_argc = argc; + *p_argv = argv; + *p_filesym = filesym; + *p_filetype = filetype; + *p_bytespersamp = bytespersamp; + *p_swap = swap; + *p_normalize = normalize; + *p_onset = onset; + *p_nframes = nframes; + *p_bigendian = bigendian; + *p_amp = amp; + return (0); +usage: + return (-1); +} + +static int create_soundfile2(t_canvas *canvas, const char *filename, + int filetype, int nframes, int bytespersamp, + int bigendian, int nchannels, int swap) +{ + char filenamebuf[MAXPDSTRING], buf2[MAXPDSTRING]; + char headerbuf[WRITEHDRSIZE]; + t_wave *wavehdr = (t_wave *)headerbuf; + t_nextstep *nexthdr = (t_nextstep *)headerbuf; + t_aiff *aiffhdr = (t_aiff *)headerbuf; + int fd, headersize = 0; + + strncpy(filenamebuf, filename, MAXPDSTRING-10); + filenamebuf[MAXPDSTRING-10] = 0; + + if (filetype == FORMAT_NEXT) + { + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".snd")) + strcat(filenamebuf, ".snd"); + if (bigendian) + strncpy(nexthdr->ns_fileid, ".snd", 4); + else strncpy(nexthdr->ns_fileid, "dns.", 4); + nexthdr->ns_onset = swap4(sizeof(*nexthdr), swap); + nexthdr->ns_length = 0; + nexthdr->ns_format = swap4((bytespersamp == 3 ? NS_FORMAT_LINEAR_24 : + (bytespersamp == 4 ? NS_FORMAT_FLOAT : NS_FORMAT_LINEAR_16)), swap);; + nexthdr->ns_sr = swap4(44100, swap); /* lie */ + nexthdr->ns_nchans = swap4(nchannels, swap); + strcpy(nexthdr->ns_info, "Pd "); + swapstring(nexthdr->ns_info, swap); + headersize = sizeof(t_nextstep); + } + else if (filetype == FORMAT_AIFF) + { + long datasize = nframes * nchannels * bytespersamp; + long longtmp; + static unsigned char dogdoo[] = + {0x40, 0x0e, 0xac, 0x44, 0, 0, 0, 0, 0, 0, 'S', 'S', 'N', 'D'}; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".aif") && + strcmp(filenamebuf + strlen(filenamebuf)-5, ".aiff")) + strcat(filenamebuf, ".aif"); + strncpy(aiffhdr->a_fileid, "FORM", 4); + aiffhdr->a_chunksize = swap4(datasize + sizeof(*aiffhdr) + 4, swap); + strncpy(aiffhdr->a_aiffid, "AIFF", 4); + strncpy(aiffhdr->a_fmtid, "COMM", 4); + aiffhdr->a_fmtchunksize = swap4(18, swap); + aiffhdr->a_nchannels = swap2(nchannels, swap); + longtmp = swap4(nframes, swap); + memcpy(&aiffhdr->a_nframeshi, &longtmp, 4); + aiffhdr->a_bitspersamp = swap2(8 * bytespersamp, swap); + memcpy(aiffhdr->a_samprate, dogdoo, sizeof(dogdoo)); + longtmp = swap4(datasize, swap); + memcpy(aiffhdr->a_samprate + sizeof(dogdoo), &longtmp, 4); + headersize = AIFFPLUS; + } + else /* WAVE format */ + { + long datasize = nframes * nchannels * bytespersamp; + if (strcmp(filenamebuf + strlen(filenamebuf)-4, ".wav")) + strcat(filenamebuf, ".wav"); + strncpy(wavehdr->w_fileid, "RIFF", 4); + wavehdr->w_chunksize = swap4(datasize + sizeof(*wavehdr) - 8, swap); + strncpy(wavehdr->w_waveid, "WAVE", 4); + strncpy(wavehdr->w_fmtid, "fmt ", 4); + wavehdr->w_fmtchunksize = swap4(16, swap); + wavehdr->w_fmttag = swap2(1, swap); + wavehdr->w_nchannels = swap2(nchannels, swap); + wavehdr->w_samplespersec = swap4(44100, swap); + wavehdr->w_navgbytespersec = swap4(44100 * nchannels * bytespersamp, swap); + wavehdr->w_nblockalign = swap2(bytespersamp, swap); + wavehdr->w_nbitspersample = swap2(8 * bytespersamp, swap); + strncpy(wavehdr->w_datachunkid, "data", 4); + wavehdr->w_datachunksize = swap4(datasize, swap); + headersize = sizeof(t_wave); + } + + canvas_makefilename(canvas, filenamebuf, buf2, MAXPDSTRING); + sys_bashfilename(buf2, buf2); + if ((fd = open(buf2, BINCREATE, 0666)) < 0) + return (-1); + + if (write(fd, headerbuf, headersize) < headersize) + { + close (fd); + return (-1); + } + return (fd); +} + +static void soundfile_finishwrite(void *obj, char *filename, int fd, + int filetype, long nframes, long itemswritten, int bytesperframe, int swap) +{ + if (itemswritten < nframes) + { + if (nframes < 0x7fffffff) + pd_error(obj, "soundfiler2_write: %d out of %d bytes written", + itemswritten, nframes); + /* try to fix size fields in header */ + if (filetype == FORMAT_WAVE) + { + long datasize = itemswritten * bytesperframe, mofo; + + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_chunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(datasize + sizeof(t_wave) - 8, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + if (lseek(fd, + ((char *)(&((t_wave *)0)->w_datachunksize)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(datasize, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + if (filetype == FORMAT_AIFF) + { + long mofo; + if (lseek(fd, + ((char *)(&((t_aiff *)0)->a_nframeshi)) - (char *)0, + SEEK_SET) == 0) + goto baddonewrite; + mofo = swap4(nframes, swap); + if (write(fd, (char *)(&mofo), 4) < 4) + goto baddonewrite; + } + } + return; +baddonewrite: + post("%s: %s", filename, strerror(errno)); +} + +static void soundfile_xferout(int nchannels, float **vecs, + unsigned char *buf, int nitems, long onset, int bytespersamp, + int bigendian, float normalfactor) +{ + int i, j; + unsigned char *sp, *sp2; + float *fp; + int bytesperframe = bytespersamp * nchannels; + long xx; + for (i = 0, sp = buf; i < nchannels; i++, sp += bytespersamp) + { + if (bytespersamp == 2) + { + float ff = normalfactor * 32768.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp = vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[0] = (xx >> 8); + sp2[1] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 32768. + (*fp * ff); + xx -= 32768; + if (xx < -32767) + xx = -32767; + if (xx > 32767) + xx = 32767; + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 3) + { + float ff = normalfactor * 8388608.; + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[0] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[2] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + int xx = 8388608. + (*fp * ff); + xx -= 8388608; + if (xx < -8388607) + xx = -8388607; + if (xx > 8388607) + xx = 8388607; + sp2[2] = (xx >> 16); + sp2[1] = (xx >> 8); + sp2[0] = xx; + } + } + } + else if (bytespersamp == 4) + { + if (bigendian) + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + float f2 = *fp * normalfactor; + xx = *(long *)&f2; + sp2[0] = (xx >> 24); sp2[1] = (xx >> 24); + sp2[2] = (xx >> 24); sp2[3] = xx; + } + } + else + { + for (j = 0, sp2 = sp, fp=vecs[i] + onset; + j < nitems; j++, sp2 += bytesperframe, fp++) + { + float f2 = *fp * normalfactor; + xx = *(long *)&f2; + sp2[3] = (xx >> 24); sp2[2] = (xx >> 24); + sp2[1] = (xx >> 24); sp2[0] = xx; + } + } + } + } +} + + +/* ------- soundfiler - reads and writes soundfiles to/from "garrays" ---- */ +#define DEFMAXSIZE 4000000 /* default maximum 16 MB per channel */ +#define SAMPBUFSIZE 1024 + + +static t_class *soundfiler2_class; + +typedef struct _soundfiler2 +{ + t_object x_obj; + t_canvas *x_canvas; +} t_soundfiler2; + +static t_soundfiler2 *soundfiler2_new(void) +{ + t_soundfiler2 *x = (t_soundfiler2 *)pd_new(soundfiler2_class); + x->x_canvas = canvas_getcurrent(); + outlet_new(&x->x_obj, &s_float); + return (x); +} + + /* soundfiler2_read ... + + usage: read [flags] filename table ... + flags: + -skip ... frames to skip in file + -nframes + -onset ... onset in table to read into (NOT DONE YET) + -raw + -resize + -maxsize + */ + +static void soundfiler2_read(t_soundfiler2 *x, t_symbol *s, + int argc, t_atom *argv) +{ + int headersize = -1, channels = 0, bytespersamp = 0, bigendian = 0, + resize = 0, i, j; + long skipframes = 0, nframes = 0, finalsize = 0, itemsleft, + maxsize = DEFMAXSIZE, itemsread = 0, bytelimit = 0x7fffffff; + int fd = -1; + char endianness, *filename; + t_garray *garrays[MAXSFCHANS]; + t_float *vecs[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes, nitems; + FILE *fp; + while (argc > 0 && argv->a_type == A_SYMBOL && + *argv->a_w.w_symbol->s_name == '-') + { + char *flag = argv->a_w.w_symbol->s_name + 1; + if (!strcmp(flag, "skip")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((skipframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "nframes")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((nframes = argv[1].a_w.w_float) < 0)) + goto usage; + argc -= 2; argv += 2; + } + else if (!strcmp(flag, "raw")) + { + if (argc < 5 || + argv[1].a_type != A_FLOAT || + ((headersize = argv[1].a_w.w_float) < 0) || + argv[2].a_type != A_FLOAT || + ((channels = argv[2].a_w.w_float) < 1) || + (channels > MAXSFCHANS) || + argv[3].a_type != A_FLOAT || + ((bytespersamp = argv[3].a_w.w_float) < 2) || + (bytespersamp > 4) || + argv[4].a_type != A_SYMBOL || + ((endianness = argv[4].a_w.w_symbol->s_name[0]) != 'b' + && endianness != 'l' && endianness != 'n')) + goto usage; + if (endianness == 'b') + bigendian = 1; + else if (endianness == 'l') + bigendian = 0; + else + bigendian = garray_ambigendian(); + argc -= 5; argv += 5; + } + else if (!strcmp(flag, "resize")) + { + resize = 1; + argc -= 1; argv += 1; + } + else if (!strcmp(flag, "maxsize")) + { + if (argc < 2 || argv[1].a_type != A_FLOAT || + ((maxsize = argv[1].a_w.w_float) < 0)) + goto usage; + resize = 1; /* maxsize implies resize. */ + argc -= 2; argv += 2; + } + else goto usage; + } + if (argc < 2 || argc > MAXSFCHANS + 1 || argv[0].a_type != A_SYMBOL) + goto usage; + filename = argv[0].a_w.w_symbol->s_name; + argc--; argv++; + + for (i = 0; i < argc; i++) + { + int vecsize; + if (argv[i].a_type != A_SYMBOL) + goto usage; + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(x, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto done; + } + else if (!garray_getfloatarray(garrays[i], &vecsize, &vecs[i])) + error("%s: bad template for tabwrite", + argv[i].a_w.w_symbol->s_name); + if (finalsize && finalsize != vecsize && !resize) + { + post("soundfiler2_read: arrays have different lengths; resizing..."); + resize = 1; + } + finalsize = vecsize; + } + fd = open_soundfile(canvas_getdir(x->x_canvas)->s_name, filename, + headersize, &bytespersamp, &bigendian, &channels, &bytelimit, + skipframes); + + if (fd < 0) + { + pd_error(x, "soundfiler2_read: %s: %s", filename, (errno == EIO ? + "unknown or bad header format" : strerror(errno))); + goto done; + } + + if (resize) + { + /* figure out what to resize to */ + long poswas, eofis, framesinfile; + + poswas = lseek(fd, 0, SEEK_CUR); + eofis = lseek(fd, 0, SEEK_END); + if (poswas < 0 || eofis < 0) + { + pd_error(x, "lseek failed"); + goto done; + } + lseek(fd, poswas, SEEK_SET); + framesinfile = (eofis - poswas) / (channels * bytespersamp); + if (framesinfile > maxsize) + { + pd_error(x, "soundfiler2_read: truncated to %d elements", maxsize); + framesinfile = maxsize; + } + if (framesinfile > bytelimit / bytespersamp) + framesinfile = bytelimit / bytespersamp; + finalsize = framesinfile; + for (i = 0; i < argc; i++) + { + int vecsize; + + garray_resize(garrays[i], finalsize); + /* for sanity's sake let's clear the save-in-patch flag here */ + garray_setsaveit(garrays[i], 0); + garray_getfloatarray(garrays[i], &vecsize, &vecs[i]); + /* if the resize failed, garray_resize reported the error */ + if (vecsize != framesinfile) + { + pd_error(x, "resize failed"); + goto done; + } + } + } + if (!finalsize) finalsize = 0x7fffffff; + if (finalsize > bytelimit / bytespersamp) + finalsize = bytelimit / bytespersamp; + fp = fdopen(fd, "rb"); + bufframes = SAMPBUFSIZE / (channels * bytespersamp); + + for (itemsread = 0; itemsread < finalsize; ) + { + int thisread = finalsize - itemsread; + thisread = (thisread > bufframes ? bufframes : thisread); + nitems = fread(sampbuf, channels * bytespersamp, thisread, fp); + if (nitems <= 0) break; + soundfile_xferin(channels, argc, vecs, itemsread, + (unsigned char *)sampbuf, nitems, bytespersamp, bigendian); + itemsread += nitems; + } + /* zero out remaining elements of vectors */ + + for (i = 0; i < argc; i++) + { + int nzero, vecsize; + garray_getfloatarray(garrays[i], &vecsize, &vecs[i]); + for (j = itemsread; j < vecsize; j++) + vecs[i][j] = 0; + } + /* zero out vectors in excess of number of channels */ + for (i = channels; i < argc; i++) + { + int vecsize; + float *foo; + garray_getfloatarray(garrays[i], &vecsize, &foo); + for (j = 0; j < vecsize; j++) + foo[j] = 0; + } + /* do all graphics updates */ + for (i = 0; i < argc; i++) + garray_redraw(garrays[i]); + fclose(fp); + fd = -1; + goto done; +usage: + pd_error(x, "usage: read [flags] filename tablename..."); + post("flags: -skip -nframes -resize -maxsize ..."); + post("-raw ."); +done: + if (fd >= 0) + close (fd); + outlet_float(x->x_obj.ob_outlet, (float)itemsread); +} + + /* this is broken out from soundfiler2_write below so garray_write can + call it too... not done yet though. */ + +static long soundfiler2_dowrite(void *obj, t_canvas *canvas, + int argc, t_atom *argv) +{ + int headersize, bytespersamp, bigendian, + endianness, swap, filetype, normalize, i, j, nchannels; + long onset, nframes, itemsleft, + maxsize = DEFMAXSIZE, itemswritten = 0; + t_garray *garrays[MAXSFCHANS]; + t_float *vecs[MAXSFCHANS]; + char sampbuf[SAMPBUFSIZE]; + int bufframes, nitems; + int fd = -1; + float normfactor, biggest = 0,ftmp,amp; + t_symbol *filesym; + + if (soundfiler2_writeargparse(obj, &argc, &argv, &filesym, &filetype, + &bytespersamp, &swap, &bigendian, &normalize, &onset, &nframes,&)) + goto usage; + nchannels = argc; + if (nchannels < 1 || nchannels > MAXSFCHANS) + goto usage; + + for (i = 0; i < nchannels; i++) + { + int vecsize; + + if (argv[i].a_type != A_SYMBOL) goto usage; + + if (!(garrays[i] = + (t_garray *)pd_findbyclass(argv[i].a_w.w_symbol, garray_class))) + { + pd_error(obj, "%s: no such table", argv[i].a_w.w_symbol->s_name); + goto fail; + } + else if (!garray_getfloatarray(garrays[i], &vecsize, &vecs[i])) + error("%s: bad template for tabwrite",argv[i].a_w.w_symbol->s_name); + if (nframes > vecsize - onset) + nframes = vecsize - onset; + + for (j = 0; j < nframes; j++) /* FIXED (Antoine Rousseau)*/ + { + ftmp=vecs[i][j+onset]; + if (ftmp > biggest) biggest = ftmp; + else if (-ftmp > biggest) biggest = -ftmp; + } + } + + if (nframes <= 0) + { + pd_error(obj, "soundfiler2_write: no samples at onset %ld", onset); + goto fail; + } + + if ((fd = create_soundfile2(canvas, filesym->s_name, filetype, + nframes, bytespersamp, bigendian, nchannels, + swap)) < 0) + { + post("%s: %s\n", filesym->s_name, strerror(errno)); + goto fail; + } + if (!normalize) + { + if ((bytespersamp != 4) && (biggest > 1)) + { + //post("%s: normalizing max amplitude %f to 1", filesym->s_name, biggest); + normalize = 1; + } + //else post("%s: biggest amplitude = %f", filesym->s_name, biggest); + } + if (normalize) + normfactor = (biggest > 0 ? 32767./(32768. * biggest) : 1); + else normfactor = amp; + + /*post("%s: biggest amplitude = %f , normfactor = %f", + filesym->s_name, biggest,normfactor);*/ + + bufframes = SAMPBUFSIZE / (nchannels * bytespersamp); + + for (itemswritten = 0; itemswritten < nframes; ) + { + int thiswrite = nframes - itemswritten, nitems, nbytes; + thiswrite = (thiswrite > bufframes ? bufframes : thiswrite); + soundfile_xferout(argc, vecs, (unsigned char *)sampbuf, thiswrite, + onset, bytespersamp, bigendian, normfactor); + nbytes = write(fd, sampbuf, nchannels * bytespersamp * thiswrite); + if (nbytes < nchannels * bytespersamp * thiswrite) + { + post("%s: %s", filesym->s_name, strerror(errno)); + if (nbytes > 0) + itemswritten += nbytes / (nchannels * bytespersamp); + break; + } + itemswritten += thiswrite; + onset += thiswrite; + } + if (fd >= 0) + { + soundfile_finishwrite(obj, filesym->s_name, fd, + filetype, nframes, itemswritten, nchannels * bytespersamp, swap); + close (fd); + } + return ((float)itemswritten); +usage: + pd_error(obj, "usage: write [flags] filename tablename..."); + post("flags: -skip -nframes -bytes -wave -aiff -nextstep ..."); + post("-big -little -normalize -amp "); + post("(defaults to a 16-bit wave file)."); +fail: + if (fd >= 0) + close (fd); + return (0); +} + +static void soundfiler2_write(t_soundfiler2 *x, t_symbol *s, + int argc, t_atom *argv) +{ + long bozo = soundfiler2_dowrite(x, x->x_canvas, + argc, argv); + outlet_float(x->x_obj.ob_outlet, (float)bozo); +} + +void soundfiler2_setup(void) +{ + soundfiler2_class = class_new(gensym("soundfiler2"), (t_newmethod)soundfiler2_new, + 0, sizeof(t_soundfiler2), 0, 0); + class_addmethod(soundfiler2_class, (t_method)soundfiler2_read, gensym("read"), + A_GIMME, 0); + class_addmethod(soundfiler2_class, (t_method)soundfiler2_write, + gensym("write"), A_GIMME, 0); +} + +/************************* readsf object ******************************/ + +/* READSF uses the Posix threads package; for the moment we're Linux +only although this should be portable to the other platforms. + +Each instance of readsf~ owns a "child" thread for doing the UNIX (NT?) file +reading. The parent thread signals the child each time: + (1) a file wants opening or closing; + (2) we've eaten another 1/16 of the shared buffer (so that the + child thread should check if it's time to read some more.) +The child signals the parent whenever a read has completed. Signalling +is done by setting "conditions" and putting data in mutex-controlled common +areas. +*/ + +#ifdef __linux__ + +#define MAXBYTESPERSAMPLE 4 +#define MAXVECSIZE 128 + +#define READSIZE 65536 +#define WRITESIZE 65536 +#define DEFBUFPERCHAN 262144 +#define MINBUFSIZE (4 * READSIZE) +#define MAXBUFSIZE 16777216 /* arbitrary; just don't want to hang malloc */ + +#define REQUEST_NOTHING 0 +#define REQUEST_OPEN 1 +#define REQUEST_CLOSE 2 +#define REQUEST_QUIT 3 +#define REQUEST_BUSY 4 + +#define STATE_IDLE 0 +#define STATE_STARTUP 1 +#define STATE_STREAM 2 + +static t_class *readsfv_class; + +static t_sample *(tmpvec[MAXSFCHANS]); + +typedef struct _readsf +{ + t_object x_obj; + t_canvas *x_canvas; + t_clock *x_clock; + char *x_buf; /* soundfile buffer */ + int x_bufsize; /* buffer size in bytes */ + int x_noutlets; /* number of audio outlets */ + t_sample *(x_outvec[MAXSFCHANS]); /* audio vectors */ + int x_vecsize; /* vector size for transfers */ + t_outlet *x_bangout; /* bang-on-done outlet */ + int x_state; /* opened, running, or idle */ + /* parameters to communicate with subthread */ + int x_requestcode; /* pending request from parent to I/O thread */ + char *x_filename; /* file to open (string is permanently allocated) */ + int x_fileerror; /* slot for "errno" return */ + int x_skipheaderbytes; /* size of header we'll skip */ + int x_bytespersample; /* bytes per sample (2 or 3) */ + int x_bigendian; /* true if file is big-endian */ + int x_sfchannels; /* number of channels in soundfile */ + long x_onsetframes; /* number of sample frames to skip */ + long x_bytelimit; /* max number of data bytes to read */ + int x_fd; /* filedesc */ + int x_fifosize; /* buffer size appropriately rounded down */ + int x_fifohead; /* index of next byte to get from file */ + int x_fifotail; /* index of next byte the ugen will read */ + int x_eof; /* true if fifohead has stopped changing */ + int x_sigcountdown; /* counter for signalling child for more data */ + int x_sigperiod; /* number of ticks per signal */ + int x_filetype; /* writesf~ only; type of file to create */ + int x_itemswritten; /* writesf~ only; items writen */ + int x_swap; /* writesf~ only; true if byte swapping */ + float x_f; /* writesf~ only; scalar for signal inlet */ + /*----HACK------*/ + float x_speed; /*speed of reading*/ + float x_frac; /*fractionnal part of sample to play next buffer*/ + + pthread_mutex_t x_mutex; + pthread_cond_t x_requestcondition; + pthread_cond_t x_answercondition; + pthread_t x_childthread; +} t_readsf; + + +/************** the child thread which performs file I/O ***********/ + +#if 0 +static void pute(char *s) /* debug routine */ +{ + write(2, s, strlen(s)); +} +#else +#define pute(x) +#endif + +#if 1 +#define sfread_cond_wait pthread_cond_wait +#define sfread_cond_signal pthread_cond_signal +#else +#include /* debugging version... */ +#include +static void readsf_fakewait(pthread_mutex_t *b) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 1000000; + pthread_mutex_unlock(b); + select(0, 0, 0, 0, &timout); + pthread_mutex_lock(b); +} + +static void readsf_banana( void) +{ + struct timeval timout; + timout.tv_sec = 0; + timout.tv_usec = 200000; + pute("banana1\n"); + select(0, 0, 0, 0, &timout); + pute("banana2\n"); +} + + +#define sfread_cond_wait(a,b) readsf_fakewait(b) +#define sfread_cond_signal(a) +#endif + +static void *readsf_child_main(void *zz) +{ + t_readsf *x = zz; + pute("1\n"); + pthread_mutex_lock(&x->x_mutex); + while (1) + { + int fd, fifohead; + char *buf; + pute("0\n"); + if (x->x_requestcode == REQUEST_NOTHING) + { + pute("wait 2\n"); + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, &x->x_mutex); + pute("3\n"); + } + else if (x->x_requestcode == REQUEST_OPEN) + { + char boo[80]; + int sysrtn, wantbytes; + + /* copy file stuff out of the data structure so we can + relinquish the mutex while we're in open_soundfile(). */ + long onsetframes = x->x_onsetframes; + long bytelimit = 0x7fffffff; + int skipheaderbytes = x->x_skipheaderbytes; + int bytespersample = x->x_bytespersample; + int sfchannels = x->x_sfchannels; + int bigendian = x->x_bigendian; + char *filename = x->x_filename; + char *dirname = canvas_getdir(x->x_canvas)->s_name; + /* alter the request code so that an ensuing "open" will get + noticed. */ + pute("4\n"); + x->x_requestcode = REQUEST_BUSY; + x->x_fileerror = 0; + + /* if there's already a file open, close it */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + if (x->x_requestcode != REQUEST_BUSY) + goto lost; + } + /* open the soundfile with the mutex unlocked */ + pthread_mutex_unlock(&x->x_mutex); + fd = open_soundfile(dirname, filename, + skipheaderbytes, &bytespersample, &bigendian, + &sfchannels, &bytelimit, onsetframes); + pthread_mutex_lock(&x->x_mutex); + + pute("5\n"); + /* copy back into the instance structure. */ + x->x_bytespersample = bytespersample; + x->x_sfchannels = sfchannels; + x->x_bigendian = bigendian; + x->x_fd = fd; + x->x_bytelimit = bytelimit; + if (fd < 0) + { + x->x_fileerror = errno; + x->x_eof = 1; + pute("open failed\n"); + pute(filename); + pute(dirname); + goto lost; + } + /* check if another request has been made; if so, field it */ + if (x->x_requestcode != REQUEST_BUSY) + goto lost; + pute("6\n"); + x->x_fifohead = 0; + /* set fifosize from bufsize. fifosize must be a + multiple of the number of bytes eaten for each DSP + tick. We pessimistically assume MAXVECSIZE samples + per tick since that could change. There could be a + problem here if the vector size increases while a + soundfile is being played... */ + x->x_fifosize = x->x_bufsize - (x->x_bufsize % + (x->x_bytespersample * x->x_sfchannels * MAXVECSIZE)); + /* arrange for the "request" condition to be signalled 16 + times per buffer */ + sprintf(boo, "fifosize %d\n", + x->x_fifosize); + pute(boo); + x->x_sigcountdown = x->x_sigperiod = + (x->x_fifosize / + (16 * x->x_bytespersample * x->x_sfchannels * + x->x_vecsize)); + /* in a loop, wait for the fifo to get hungry and feed it */ + + while (x->x_requestcode == REQUEST_BUSY) + { + int fifosize = x->x_fifosize; + pute("77\n"); + if (x->x_eof) + break; + if (x->x_fifohead >= x->x_fifotail) + { + /* if the head is >= the tail, we can immediately read + to the end of the fifo. Unless, that is, we would + read all the way to the end of the buffer and the + "tail" is zero; this would fill the buffer completely + which isn't allowed because you can't tell a completely + full buffer from an empty one. */ + if (x->x_fifotail || (fifosize - x->x_fifohead > READSIZE)) + { + wantbytes = fifosize - x->x_fifohead; + if (wantbytes > READSIZE) + wantbytes = READSIZE; + if (wantbytes > x->x_bytelimit) + wantbytes = x->x_bytelimit; + sprintf(boo, "head %d, tail %d, size %d\n", + x->x_fifohead, x->x_fifotail, wantbytes); + pute(boo); + } + else + { + pute("wait 7a ...\n"); + sfread_cond_signal(&x->x_answercondition); + pute("signalled\n"); + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); + pute("7a done\n"); + continue; + } + } + else + { + /* otherwise check if there are at least READSIZE + bytes to read. If not, wait and loop back. */ + wantbytes = x->x_fifotail - x->x_fifohead - 1; + if (wantbytes < READSIZE) + { + pute("wait 7...\n"); + sfread_cond_signal(&x->x_answercondition); + sfread_cond_wait(&x->x_requestcondition, + &x->x_mutex); + pute("7 done\n"); + continue; + } + else wantbytes = READSIZE; + } + pute("8\n"); + fd = x->x_fd; + buf = x->x_buf; + fifohead = x->x_fifohead; + pthread_mutex_unlock(&x->x_mutex); + sysrtn = read(fd, buf + fifohead, wantbytes); + pthread_mutex_lock(&x->x_mutex); + if (x->x_requestcode != REQUEST_BUSY) + break; + if (sysrtn < 0) + { + pute("fileerror\n"); + x->x_fileerror = errno; + break; + } + else if (sysrtn == 0) + { + x->x_eof = 1; + break; + } + else + { + x->x_fifohead += sysrtn; + x->x_bytelimit -= sysrtn; + if (x->x_bytelimit <= 0) + { + x->x_eof = 1; + break; + } + if (x->x_fifohead == fifosize) + x->x_fifohead = 0; + } + sprintf(boo, "after: head %d, tail %d\n", + x->x_fifohead, x->x_fifotail); + pute(boo); + /* signal parent in case it's waiting for data */ + sfread_cond_signal(&x->x_answercondition); + } + lost: + + if (x->x_requestcode == REQUEST_BUSY) + x->x_requestcode = REQUEST_NOTHING; + /* fell out of read loop: close file if necessary, + set EOF and signal once more */ + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + sfread_cond_signal(&x->x_answercondition); + + } + else if (x->x_requestcode == REQUEST_CLOSE) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + if (x->x_requestcode == REQUEST_CLOSE) + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + } + else if (x->x_requestcode == REQUEST_QUIT) + { + if (x->x_fd >= 0) + { + fd = x->x_fd; + pthread_mutex_unlock(&x->x_mutex); + close (fd); + pthread_mutex_lock(&x->x_mutex); + x->x_fd = -1; + } + x->x_requestcode = REQUEST_NOTHING; + sfread_cond_signal(&x->x_answercondition); + break; + } + else + { + pute("13\n"); + } + } + pute("thread exit\n"); + pthread_mutex_unlock(&x->x_mutex); + return (0); +} + +/******** the object proper runs in the calling (parent) thread ****/ + +static void readsf_tick(t_readsf *x); + +static void *readsf_new(t_floatarg fnchannels, t_floatarg fbufsize) +{ + t_readsf *x; + int nchannels = fnchannels, bufsize = fbufsize, i; + char *buf; + + if (nchannels < 1) + nchannels = 1; + else if (nchannels > MAXSFCHANS) + nchannels = MAXSFCHANS; + if (bufsize <= 0) bufsize = DEFBUFPERCHAN * nchannels; + else if (bufsize < MINBUFSIZE) + bufsize = MINBUFSIZE; + else if (bufsize > MAXBUFSIZE) + bufsize = MAXBUFSIZE; + buf = getbytes(bufsize); + if (!buf) return (0); + + x = (t_readsf *)pd_new(readsfv_class); + + for (i = 0; i < nchannels; i++) + outlet_new(&x->x_obj, gensym("signal")); + x->x_noutlets = nchannels; + x->x_bangout = outlet_new(&x->x_obj, &s_bang); + pthread_mutex_init(&x->x_mutex, 0); + pthread_cond_init(&x->x_requestcondition, 0); + pthread_cond_init(&x->x_answercondition, 0); + x->x_vecsize = MAXVECSIZE; + x->x_state = STATE_IDLE; + x->x_clock = clock_new(x, (t_method)readsf_tick); + x->x_canvas = canvas_getcurrent(); + x->x_bytespersample = 2; + x->x_sfchannels = 1; + x->x_fd = -1; + x->x_buf = buf; + x->x_bufsize = bufsize; + x->x_fifosize = x->x_fifohead = x->x_fifotail = x->x_requestcode = 0; + pthread_create(&x->x_childthread, 0, readsf_child_main, x); + return (x); +} + +static void readsf_tick(t_readsf *x) +{ + outlet_bang(x->x_bangout); +} + +static t_int *readsf_perform(t_int *w) +{ + t_readsf *x = (t_readsf *)(w[1]); + int vecsize = x->x_vecsize, noutlets = x->x_noutlets, i, j, + bytespersample = x->x_bytespersample, + bigendian = x->x_bigendian,wantsamples; + float *fp,tmp,speed=x->x_speed; + if (x->x_state == STATE_STREAM) + { + int wantbytes, nchannels, sfchannels = x->x_sfchannels; + pthread_mutex_lock(&x->x_mutex); + tmp=vecsize *speed+x->x_frac; + wantsamples=(int)tmp; + x->x_frac=tmp-wantsamples; + + if(!speed) goto idle; + + wantbytes = sfchannels * wantsamples * bytespersample; + + while ( + !x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { + pute("wait...\n"); + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + pute("done\n"); + } + if (x->x_eof && x->x_fifohead >= x->x_fifotail && + x->x_fifohead < x->x_fifotail + wantbytes-1) + { + if (x->x_fileerror) + { + pd_error(x, "dsp: %s: %s", x->x_filename, + (x->x_fileerror == EIO ? + "unknown or bad header format" : + strerror(x->x_fileerror))); + } + clock_delay(x->x_clock, 0); + x->x_state = STATE_IDLE; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); + goto idle; + } + + if(speed==1) + soundfile_xferin(sfchannels, noutlets, x->x_outvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), vecsize, + bytespersample, bigendian); + else { + soundfile_xferin(sfchannels, noutlets, tmpvec, 0, + (unsigned char *)(x->x_buf + x->x_fifotail), wantsamples, + bytespersample, bigendian); + interpolate(noutlets,tmpvec,wantsamples,x->x_outvec,vecsize); + } + + x->x_fifotail += wantbytes; + if (x->x_fifotail >= x->x_fifosize) + x->x_fifotail = 0; + if ((--x->x_sigcountdown) <= 0) + { + sfread_cond_signal(&x->x_requestcondition); + x->x_sigcountdown = x->x_sigperiod; + } + pthread_mutex_unlock(&x->x_mutex); + } + else + { + idle: + for (i = 0; i < noutlets; i++) + for (j = vecsize, fp = x->x_outvec[i]; j--; ) + *fp++ = 0; + } + return (w+2); +} + +static void readsf_start(t_readsf *x) +{ + /* start making output. If we're in the "startup" state change + to the "running" state. */ + if (x->x_state == STATE_STARTUP) + x->x_state = STATE_STREAM; + else pd_error(x, "readsf: start requested with no prior 'open'"); +} + +static void readsf_stop(t_readsf *x) +{ + /* LATER rethink whether you need the mutex just to set a variable? */ + pthread_mutex_lock(&x->x_mutex); + x->x_state = STATE_IDLE; + x->x_requestcode = REQUEST_CLOSE; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_float(t_readsf *x, t_floatarg f) +{ + if (f != 0) + readsf_start(x); + else readsf_stop(x); +} + +static void readsf_speed(t_readsf *x, t_floatarg f) +{ + if((f>=0)&&(f<=8)) + x->x_speed=f; +} + + /* open method. Called as: + open filename [skipframes headersize channels bytespersamp endianness] + (if headersize is zero, header is taken to be automatically + detected; thus, use the special "-1" to mean a truly headerless file.) + */ + +static void readsf_open(t_readsf *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *filesym = atom_getsymbolarg(0, argc, argv); + t_float onsetframes = atom_getfloatarg(1, argc, argv); + t_float headerbytes = atom_getfloatarg(2, argc, argv); + t_float channels = atom_getfloatarg(3, argc, argv); + t_float bytespersamp = atom_getfloatarg(4, argc, argv); + t_symbol *endian = atom_getsymbolarg(5, argc, argv); + if (!*filesym->s_name) + return; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_OPEN; + x->x_filename = filesym->s_name; + x->x_fifotail = 0; + x->x_fifohead = 0; + if (*endian->s_name == 'b') + x->x_bigendian = 1; + else if (*endian->s_name == 'l') + x->x_bigendian = 0; + else if (*endian->s_name) + pd_error(x, "endianness neither 'b' nor 'l'"); + else x->x_bigendian = garray_ambigendian(); + x->x_onsetframes = (onsetframes > 0 ? onsetframes : 0); + x->x_skipheaderbytes = (headerbytes > 0 ? headerbytes : + (headerbytes == 0 ? -1 : 0)); + x->x_sfchannels = (channels >= 1 ? channels : 1); + x->x_bytespersample = (bytespersamp > 2 ? bytespersamp : 2); + x->x_eof = 0; + x->x_fileerror = 0; + x->x_state = STATE_STARTUP; + x->x_speed=1; + x->x_frac=0; + sfread_cond_signal(&x->x_requestcondition); + pthread_mutex_unlock(&x->x_mutex); +} + +static void readsf_dsp(t_readsf *x, t_signal **sp) +{ + int i, noutlets = x->x_noutlets; + pthread_mutex_lock(&x->x_mutex); + x->x_vecsize = sp[0]->s_n; + + x->x_sigperiod = (x->x_fifosize / + (x->x_bytespersample * x->x_sfchannels * x->x_vecsize)); + for (i = 0; i < noutlets; i++) + x->x_outvec[i] = sp[i]->s_vec; + pthread_mutex_unlock(&x->x_mutex); + dsp_add(readsf_perform, 1, x); +} + +static void readsf_print(t_readsf *x) +{ + post("state %d", x->x_state); + post("fifo head %d", x->x_fifohead); + post("fifo tail %d", x->x_fifotail); + post("fifo size %d", x->x_fifosize); + post("fd %d", x->x_fd); + post("eof %d", x->x_eof); +} + +static void readsf_free(t_readsf *x) +{ + /* request QUIT and wait for acknowledge */ + void *threadrtn; + pthread_mutex_lock(&x->x_mutex); + x->x_requestcode = REQUEST_QUIT; + post("stopping readsf thread..."); + sfread_cond_signal(&x->x_requestcondition); + while (x->x_requestcode != REQUEST_NOTHING) + { + post("signalling..."); + sfread_cond_signal(&x->x_requestcondition); + sfread_cond_wait(&x->x_answercondition, &x->x_mutex); + } + pthread_mutex_unlock(&x->x_mutex); + if (pthread_join(x->x_childthread, &threadrtn)) + error("readsf_free: join failed"); + post("... done."); + + pthread_cond_destroy(&x->x_requestcondition); + pthread_cond_destroy(&x->x_answercondition); + pthread_mutex_destroy(&x->x_mutex); + freebytes(x->x_buf, x->x_bufsize); + clock_free(x->x_clock); +} + +#endif /* __linux__ */ + +void readsfv_tilde_setup(void) +{ +#ifdef __linux__ + int i; + + readsfv_class = class_new(gensym("readsfv~"), (t_newmethod)readsf_new, + (t_method)readsf_free, sizeof(t_readsf), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + + class_addfloat(readsfv_class, (t_method)readsf_float); + class_addmethod(readsfv_class, (t_method)readsf_speed, gensym("speed"), A_FLOAT,0); + class_addmethod(readsfv_class, (t_method)readsf_start, gensym("start"), 0); + class_addmethod(readsfv_class, (t_method)readsf_stop, gensym("stop"), 0); + class_addmethod(readsfv_class, (t_method)readsf_dsp, gensym("dsp"), 0); + class_addmethod(readsfv_class, (t_method)readsf_open, gensym("open"), + A_GIMME, 0); + class_addmethod(readsfv_class, (t_method)readsf_print, gensym("print"), 0); + + for(i=0;i*/ +#include "m_pd.h" +#include "g_canvas.h" + +#include +#include +#include +#include +#include +#include + +extern t_canvas *canvas_list; /* list of all root canvases */ +extern int canvas_getdollarzero( void); + +struct _canvasenvironment +{ + t_symbol *ce_dir; /* directory patch lives in */ + int ce_argc; /* number of "$" arguments */ + t_atom *ce_argv; /* array of "$" arguments */ + int ce_dollarzero; /* value of "$0" */ +}; + +typedef struct _relativepath +{ + t_object x_obj; + t_canvas *x_canvas; + int x_dolzero; + int x_realized; +}t_relativepath; + +t_class *relativepath_class; + +void relativepath_setup(void); + +static t_glist *getcanvas(t_glist *can,int d0) +{ + t_canvas *retcan=0; + t_gobj *ob; + + if((can->gl_env)&&(can->gl_env->ce_dollarzero==d0)){ + return can; + } + + ob=can->gl_list; + while(ob&&(retcan==0)) { + if (pd_class(&ob->g_pd) == canvas_class) + retcan=getcanvas((t_glist *)ob,d0); + ob=ob->g_next; + } + + if((!retcan)&&(can->gl_next)) retcan=getcanvas((t_glist *)can->gl_next,d0); + return retcan; +} + +static void relativepath_symbol(t_relativepath *x,t_symbol *sym) +{ + t_canvas *can=0; + t_symbol *s=sym; + char *instr=sym->s_name,*outstr=instr, + *candir, + canname[MAXPDSTRING],totaldir[MAXPDSTRING], + *cnamedir; + unsigned int n,i=0; + + if(!x->x_realized) can=(t_canvas*)getcanvas(canvas_list,x->x_dolzero); + if(can) { + x->x_canvas = can; + x->x_realized = 1; + //post("found $0 canvas : %x %d ",x->x_canvas, x->x_canvas->gl_env->ce_dollarzero ); + } + + if(!instr) return; + + candir=canvas_getdir(x->x_canvas)->s_name; + if(!candir) candir=""; + + strcpy(canname,x->x_canvas->gl_name->s_name); + //post("canname=%s",canname); + cnamedir=dirname(canname); + + if (strcmp(cnamedir,".")) { + sprintf(totaldir,"%s/%s",candir,cnamedir); + } + else + strcpy(totaldir,candir); + + //post("dir=%s",totaldir); + + n=strlen(totaldir); + if(strlen(instr)<=n) goto end; + + while(ix_obj.ob_outlet,s); +} + + +static void *relativepath_new(t_float dolzero) +{ + t_relativepath *x = (t_relativepath *)pd_new(relativepath_class); + int d0; + + outlet_new(&x->x_obj, 0); + x->x_canvas = canvas_getcurrent(); + x->x_dolzero = dolzero; + x->x_realized=dolzero?0:1; + + return (void *)x; +} + +void relativepath_setup(void) +{ + relativepath_class = class_new(gensym("relativepath"),(t_newmethod)relativepath_new, + 0, sizeof(t_relativepath), 0,A_DEFFLOAT,0); + + class_addsymbol(relativepath_class, relativepath_symbol); +} + diff --git a/s2f.c b/s2f.c new file mode 100644 index 0000000..3e36b22 --- /dev/null +++ b/s2f.c @@ -0,0 +1,53 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include + +typedef struct _s2f +{ + t_object x_obj; +}t_s2f; + +t_class *s2f_class; + +void s2f_setup(void); + +static void s2f_symbol(t_s2f *x,t_symbol *sym) +{ + if(!sym->s_name) return; + + outlet_float(x->x_obj.ob_outlet,(float)strtod(sym->s_name,0)); +} + +static void *s2f_new(void) +{ + t_s2f *x = (t_s2f *)pd_new(s2f_class); + outlet_new(&x->x_obj, &s_float); + return (void *)x; +} + +void s2f_setup(void) +{ + s2f_class = class_new(gensym("s2f"),(t_newmethod)s2f_new, + 0, sizeof(t_s2f), 0, 0); + + class_addsymbol(s2f_class, s2f_symbol); +} + diff --git a/sarray.c b/sarray.c new file mode 100644 index 0000000..d44f7ce --- /dev/null +++ b/sarray.c @@ -0,0 +1,264 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol array, ala "value" .*/ + +#include "m_pd.h" +#include +#include + +static t_class *sarray_class, *scommon_class; +static t_symbol *s__; + +typedef struct scommon +{ + t_pd c_pd; + t_symbol *c_sym; + int c_refcount; + int c_len; + t_symbol **c_array; +} t_scommon; + +typedef struct _sarray +{ + t_object x_obj; + t_symbol *x_sym; + t_scommon *x_c; + //t_outlet *x_symout; + //t_outlet *x_lenout; +} t_sarray; + +/*static int scommon_find(t_scommon *x, t_symbol *s) +{ + t_sitem *si=x->first; + t_int i=1; + + while(si) { + if(!strcmp(si->s->s_name,s->s_name)) return i; + si=si->next; + i++; + } + return 0; +}*/ + +static t_symbol *scommon_get(t_scommon *x, t_float f) +{ + int i=(int)f; + + if(i<0) i=0; + if(i>=x->c_len) i=x->c_len-1; + return x->c_array[i]; +} + +static void scommon_set(t_scommon *x, t_float f, t_symbol *s) +{ + int i=(int)f; + + if((i<0)||(i>=x->c_len)) return; + x->c_array[i]=s; + //x->c_array[i]=gensym(strdup(s->s_name)); + //x->c_array[i]=gensym("ok"); +} + +static void scommon_setlen(t_scommon *x, t_float flen) +{ + int i,oldlen=x->c_len,len=flen; + + if(len<1) len=1; + x->c_len=len; + + x->c_array=realloc(x->c_array,sizeof(t_symbol *)*len); + + if(len>oldlen) for(i=oldlen;ic_array[i]=&s_; +} + +static void scommon_reset(t_scommon *x) +{ + int i; + + for(i=0;ic_len;i++) x->c_array[i]=&s_; +} + +static t_atom *scommon_dump(t_scommon *x,t_symbol *s) +{ + int i; + t_atom *atombuf; + + atombuf = (t_atom *)getbytes(sizeof(t_atom)*x->c_len); + + for(i=0;ic_len;i++) { + if(x->c_array[i]==&s_) SETSYMBOL(&atombuf[i],s); + else SETSYMBOL(&atombuf[i],x->c_array[i]); + } + + return atombuf; +} + +static void scommon_ff(t_scommon *x) +{ + //scommon_reset(x); + pd_unbind((t_pd*)x, x->c_sym); +} + +static void *scommon_new(t_symbol *s) +{ + t_scommon *x = (t_scommon *)pd_new(scommon_class); + + x->c_refcount = 0; + x->c_sym=s; + pd_bind((t_pd*)x, s); + + x->c_len=1; + x->c_array=malloc(sizeof(t_symbol *)*1); + scommon_reset(x); + + return (x); +} + + + /* get a pointer to a named symbol list (a "scommon" object), + which is created if necessary. */ +t_scommon *sarray_scget(t_symbol *s) +{ + t_scommon *c = (t_scommon *)pd_findbyclass(s, scommon_class); + + if (!c) c = (t_scommon *)scommon_new(s); + c->c_refcount++; + return (c); +} + + /* release a variable. This only frees the "scommon" resource when the + last interested party releases it. */ +void sarray_release(t_scommon *c) +{ + if (!--c->c_refcount) scommon_ff(c); +} + + +static void *sarray_new(t_symbol *s,t_float len) +{ + t_sarray *x = (t_sarray *)pd_new(sarray_class); + + x->x_sym = s; + x->x_c = sarray_scget(s); + if(len) scommon_setlen(x->x_c,len); + + outlet_new(&x->x_obj, &s_anything); + //x->x_symout=outlet_new(&x->x_obj, &s_anything); + //x->x_lenout=outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void sarray_ff(t_sarray *x) +{ + sarray_release(x->x_c); +} + +static void sarray_print(t_sarray *x) +{ + int i; + + for(i=0;ix_c->c_len;i++){ + post("item %d: %s",i,x->x_c->c_array[i]->s_name); + } +} + +static void sarray_reset(t_sarray *x) +{ + scommon_reset(x->x_c); +} + +static void sarray_set(t_sarray *x, t_symbol *sfoo,int argc, t_atom *argv) +{ + int i,j=0; + t_symbol *snull=&s_,*s; + + /*if((argc<2)||(argv[0].a_type!=A_FLOAT)) + { + error("Bad arguments for message 'set' to object 'sarray'"); + return ; + }*/ + if(argv[0].a_type==A_SYMBOL) { + snull=atom_getsymbol(&argv[0]); + j=1; + } + + if(argv[j].a_type!=A_FLOAT){ + error("Bad arguments for message 'set' to object 'sarray'"); + return ; + } + + i=atom_getfloat(&argv[j++]); + + while((jx_c,i++,s); + } +} + +static void sarray_get(t_sarray *x,t_float i) +{ + t_symbol *s=scommon_get(x->x_c,i); + + if(s==&s_) outlet_bang(x->x_obj.ob_outlet); + else outlet_symbol(x->x_obj.ob_outlet,scommon_get(x->x_c,i)); +} + +static void sarray_dump(t_sarray *x,t_symbol *s) +{ + t_atom *l=scommon_dump(x->x_c,s); + + outlet_list(x->x_obj.ob_outlet, &s_list, x->x_c->c_len, l); + free(l); +} + +static void sarray_setarray(t_sarray *x,t_symbol *s) +{ + sarray_release(x->x_c); + x->x_c = sarray_scget(s); + x->x_sym = s; +} + +static void sarray_setlen(t_sarray *x,t_float len) +{ + scommon_setlen(x->x_c,len); +} + + +void sarray_setup(void) +{ + s__=gensym("_"); + sarray_class = class_new(gensym("sarray"), (t_newmethod)sarray_new, + (t_method)sarray_ff, + sizeof(t_sarray), 0, A_DEFSYM, A_DEFFLOAT,0); + + //class_addbang(sarray_class, sarray_bang); + //class_addfloat(sarray_class, sarray_float); + class_addmethod(sarray_class,(t_method)sarray_set, gensym("set"),A_GIMME,0); + class_addmethod(sarray_class,(t_method)sarray_get, gensym("get"),A_FLOAT,0); + class_addmethod(sarray_class,(t_method)sarray_reset, gensym("reset"),0); + class_addmethod(sarray_class,(t_method)sarray_print, gensym("print"),0); + class_addmethod(sarray_class,(t_method)sarray_setlen, gensym("setlen"),A_FLOAT,0); + class_addmethod(sarray_class,(t_method)sarray_dump, gensym("dump"),A_DEFSYM,0); + class_addmethod(sarray_class,(t_method)sarray_setarray, gensym("setarray"),A_SYMBOL,0); + scommon_class = class_new(gensym("sarray"), 0, 0, + sizeof(t_scommon), CLASS_PD, 0); +} + diff --git a/sfread2~.c b/sfread2~.c new file mode 100644 index 0000000..aceb39e --- /dev/null +++ b/sfread2~.c @@ -0,0 +1,410 @@ +#include +//#include +#include "g_canvas.h" +#ifdef NT +#pragma warning( disable : 4244 ) +#pragma warning( disable : 4305 ) +#endif + +#include +#include +#ifndef NT +#include +#include +#else +#include +#endif + + +#include +#include + +/* ------------------------ sfread~ ----------------------------- */ + +#ifdef NT +#define BINREADMODE "rb" +#else +#define BINREADMODE "r" +#endif + +static t_class *sfread_class; + + +typedef struct _sfread +{ + t_object x_obj; + void* x_mapaddr; + int x_fd; + + t_int x_play; + t_int x_outchannels; + t_int x_loop; + double x_index; //samples + t_float x_speed; //1=sample rate + t_int x_interp; + + t_int x_size; // bytes + t_int x_fchannels; // file channels + t_int x_len; // samples + t_int x_skip; //bytes + t_clock *x_clock; + + + t_glist * x_glist; + t_outlet *x_stateout; + t_outlet *x_sizeout; +} t_sfread; + +#define MAX_CHANS 4 + + + +//1 -> 2 + +//1 -> 4 + +//2 -> 4 + + +static t_int *sfread_perform(t_int *w) +{ + t_sfread* x = (t_sfread*)(w[1]); + short *fp, *buf = x->x_mapaddr+x->x_skip; +/* t_float *in = (t_float *)(w[2]); will we need this (indexing) ?*/ + int c = x->x_outchannels; + int fc = x->x_fchannels,fc2=2*fc; + double findex = x->x_index; + t_float speed = x->x_speed; + float frac, a, b, cc, d, cminusb; + int i,n,index,rindex; + int end = x->x_len -3;/* -3 is for safe interpolation*/ + t_float* out[MAX_CHANS]; + t_int in_off[MAX_CHANS]; + t_int loground=(fc==1?0:fc==2?1:2); + + if(!x->x_mapaddr) return(w+c+4); + + for (i=0;i end) + findex = end; + + if (findex + n*speed > end) { // playing forward end + if (!x->x_loop) { + x->x_play=0; + findex = 0; + clock_delay(x->x_clock, 0); + } + } + + if (findex + n*speed < 1) { // playing backwards end + if (!x->x_loop) { + x->x_play=0; + findex = end; + clock_delay(x->x_clock, 0); + } + + } + + + if (x->x_play && x->x_mapaddr) { + + if (speed != 1) { /* different speed */ + if (x->x_interp) while (n--) { + index=findex; + rindex=index< end) { + if (x->x_loop) findex = 1; + else break; + } + if (findex < 1) { + if (x->x_loop) findex = end; + else break; + } + } + else while (n--) { + rindex=((int)findex)< end) { + if (x->x_loop) findex = 1; + else break; + } + if (findex < 1) { + if (x->x_loop) findex = end; + else break; + } + } + /* Fill with zero in case of end */ + n++; + while (n--) + for (i=0;i end2) { + if (x->x_loop) rindex = 1; + else break; + } + } + + /* Fill with zero in case of end */ + n++; + while (n--) + for (i=0;i>loground; + } + + } + else { + while (n--) { + for (i=0;ix_index = findex; + return (w+c+4); +} + + +static void sfread_loop(t_sfread *x, t_floatarg f) +{ + x->x_loop = f; +} + +static void sfread_interp(t_sfread *x, t_floatarg f) +{ + x->x_interp = (f!=0); +} + +static void sfread_index(t_sfread *x, t_floatarg f) +{ + x->x_index = f; +} + + +static void sfread_size(t_sfread* x) +{ + outlet_float(x->x_sizeout,x->x_len); +} + +static void sfread_state(t_sfread* x) +{ + outlet_float(x->x_stateout, x->x_play); +} + +static void sfread_float(t_sfread *x, t_floatarg f) +{ + int t = f; + if (t && x->x_mapaddr) { + x->x_play=1; + } + else { + x->x_play=0; + } + sfread_state(x); +} + + +static void sfread_bang(t_sfread* x) +{ + x->x_index = x->x_speed>0?1:x->x_len-3; + sfread_float(x,1.0); +} + + +static void sfread_dsp(t_sfread *x, t_signal **sp) +{ +/* post("sfread: dsp"); */ + switch (x->x_outchannels) { + case 1: + dsp_add(sfread_perform, 4, x, sp[0]->s_vec, + sp[1]->s_vec, sp[0]->s_n); + break; + case 2: + dsp_add(sfread_perform, 5, x, sp[0]->s_vec, + sp[1]->s_vec,sp[2]->s_vec, sp[0]->s_n); + break; + case 4: + dsp_add(sfread_perform, 6, x, sp[0]->s_vec, + sp[1]->s_vec,sp[2]->s_vec, + sp[3]->s_vec,sp[4]->s_vec, + sp[0]->s_n); + break; + } +} + + +extern int open_soundfile(const char *dirname, const char *filename, int headersize, + int *p_bytespersamp, int *p_bigendian, int *p_nchannels, long *p_bytelimit, + long skipframes); /* in pd/src/d_soundfile.c */ + + +static void sfread_open(t_sfread *x,t_symbol *filename) +{ + struct stat fstate; + char fname[MAXPDSTRING]; + int bytespersamp=0,bigendian=0,channels=0; + long bytelimit= 0x7fffffff,skipframes = 0; + + if (filename == &s_) { + post("sfread: open without filename"); + return; + } + + canvas_makefilename(glist_getcanvas(x->x_glist), filename->s_name, + fname, MAXPDSTRING); + + + /* close the old file */ + + if (x->x_mapaddr) munmap(x->x_mapaddr,x->x_size); + if (x->x_fd >= 0) close(x->x_fd); + + /*if ((x->x_fd = open(fname,O_RDONLY)) < 0)*/ + //post("fname: %s",fname); + + if ((x->x_fd = open_soundfile("",fname, -1,&bytespersamp,&bigendian, + &channels, &bytelimit,0)) < 0) + { + error("can't open %s",fname); + x->x_play = 0; + x->x_mapaddr = NULL; + return; + } + + if( ((x->x_fchannels!=1)&&(x->x_fchannels!=2)&&(x->x_fchannels!=4)) || + (bytespersamp!=2) ) + { + error("file %s error: not a 1 or 2 or 4 channels soundfile, or not a 16 bits soundfile",fname); + post("channels:%d bytes:%d ",x->x_fchannels,bytespersamp); + x->x_play = 0; + x->x_mapaddr = NULL; + return; + } + + x->x_fchannels=channels; + + /* get the size */ + + fstat(x->x_fd,&fstate); + x->x_size = (int)fstate.st_size; + x->x_skip=x->x_size-bytelimit; + x->x_len = (bytelimit)/(bytespersamp*x->x_fchannels); + + //post("bytelimit=%d x->x_size-x->x_skip=%d x->x_size=%d x->x_skip=%d",bytelimit,x->x_size-x->x_skip,x->x_size,x->x_skip); + + /* map the file into memory */ + + if (!(x->x_mapaddr = mmap(NULL,x->x_size,PROT_READ,MAP_PRIVATE,x->x_fd,0))) + { + error("can't mmap %s",fname); + return; + } + sfread_size(x); +} + +static void *sfread_new(t_floatarg chan,t_floatarg interp) +{ + t_sfread *x = (t_sfread *)pd_new(sfread_class); + t_int c = chan; + + x->x_glist = (t_glist*) canvas_getcurrent(); + + if (c<1 || c > MAX_CHANS) c = 1; + floatinlet_new(&x->x_obj, &x->x_speed); + + + x->x_fd = -1; + x->x_mapaddr = NULL; + + x->x_size = 0; + x->x_len = 0; + x->x_loop = 0; + x->x_outchannels = c; + x->x_fchannels = 1; + x->x_mapaddr=NULL; + x->x_index = 1; + x->x_skip = 0; + x->x_speed = 1.0; + x->x_play = 0; + x->x_interp = (interp!=0); + x->x_clock = clock_new(x, (t_method)sfread_state); + + while (c--) { + outlet_new(&x->x_obj, gensym("signal")); + } + + x->x_stateout = outlet_new(&x->x_obj, &s_float); + x->x_sizeout = outlet_new(&x->x_obj, &s_float); + +/* post("sfread: x_channels = %d, x_speed = %f",x->x_channels,x->x_speed);*/ + + return (x); +} + +static void sfread_free(t_sfread *x) +{ + clock_free(x->x_clock); +} + +void sfread2_tilde_setup(void) +{ + /* sfread */ + + sfread_class = class_new(gensym("sfread2~"), (t_newmethod)sfread_new, + (t_method)sfread_free,sizeof(t_sfread), 0,A_DEFFLOAT,A_DEFFLOAT,0); + + class_addmethod(sfread_class, nullfn, gensym("signal"), 0); + class_addmethod(sfread_class, (t_method) sfread_dsp, gensym("dsp"), 0); + class_addmethod(sfread_class, (t_method) sfread_open, gensym("open"), A_SYMBOL,A_NULL); + class_addmethod(sfread_class, (t_method) sfread_size, gensym("size"), 0); + class_addmethod(sfread_class, (t_method) sfread_state, gensym("state"), 0); + class_addfloat(sfread_class, sfread_float); + class_addbang(sfread_class,sfread_bang); + class_addmethod(sfread_class,(t_method)sfread_loop,gensym("loop"),A_FLOAT,A_NULL); + class_addmethod(sfread_class,(t_method)sfread_interp,gensym("interp"),A_FLOAT,A_NULL); + class_addmethod(sfread_class,(t_method)sfread_index,gensym("index"),A_FLOAT,A_NULL); + + + // Impossible with pd-0.35 because it leaves super-user mode. + //if(munlockall()) perror("munlockall()"); + //if(mlockall(MCL_CURRENT)) perror("mlockall(MCL_CURRENT)"); +} + + + + + + diff --git a/slist.c b/slist.c new file mode 100644 index 0000000..6af28c6 --- /dev/null +++ b/slist.c @@ -0,0 +1,233 @@ +/* +Copyright (C) 2003 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a shared symbol list, ala "value" .*/ + +#include +#include +#include + +static t_class *slist_class, *scommon_class; + +typedef struct _sitem t_sitem; + +struct _sitem +{ + t_sitem *next; + t_symbol *s; +}; + +typedef struct scommon +{ + t_pd c_pd; + t_symbol *c_sym; + int c_refcount; + t_sitem *first; +} t_scommon; + +typedef struct _slist +{ + t_object x_obj; + t_symbol *x_sym; + t_scommon *x_c; + t_outlet *x_symout; + t_outlet *x_lenout; +} t_slist; + + +static void sitem_delete(t_sitem **x) +{ + t_sitem *next=(*x)->next; + + //freebytes((*x)->name,strlen((*x)->name)+1); + freebytes(*x,sizeof(t_sitem)); + (*x)=next; +} + +static void sitem_add(t_sitem **x,t_symbol *s) +{ + t_int l; + t_sitem *newone=getbytes(sizeof(t_sitem)); + + //newone->name=getbytes(l=(strlen(s->s_name)+1)); + //strncpy(newone->name,s->s_name,l); + newone->s=s; + newone->next=0; + + while(*x) x=&((*x)->next); + + *x=newone; +} + +static void *scommon_new(t_symbol *s) +{ + t_scommon *x = (t_scommon *)pd_new(scommon_class); + + x->c_refcount = 0; + x->c_sym=s; + pd_bind((t_pd*)x, s); + + x->first=0; + + return (x); +} + +static int scommon_find(t_scommon *x, t_symbol *s) +{ + t_sitem *si=x->first; + t_int i=1; + + while(si) { + if(!strcmp(si->s->s_name,s->s_name)) return i; + si=si->next; + i++; + } + return 0; +} + +static void scommon_add(t_scommon *x, t_symbol *s) +{ + sitem_add(&x->first,s); +} + +static void scommon_reset(t_scommon *x) +{ + while(x->first) sitem_delete(&x->first); +} + +static void scommon_ff(t_scommon *x) +{ + scommon_reset(x); + pd_unbind((t_pd*)x, x->c_sym); +} + + + /* get a pointer to a named symbol list (a "scommon" object), + which is created if necessary. */ +t_scommon *slist_get(t_symbol *s) +{ + t_scommon *c = (t_scommon *)pd_findbyclass(s, scommon_class); + + if (!c) c = (t_scommon *)scommon_new(s); + c->c_refcount++; + return (c); +} + + /* release a variable. This only frees the "scommon" resource when the + last interested party releases it. */ +void slist_release(t_scommon *c) +{ + if (!--c->c_refcount) scommon_ff(c); +} + + +static void *slist_new(t_symbol *s) +{ + t_slist *x = (t_slist *)pd_new(slist_class); + x->x_sym = s; + x->x_c = slist_get(s); + outlet_new(&x->x_obj, &s_float); + x->x_symout=outlet_new(&x->x_obj, &s_symbol); + x->x_lenout=outlet_new(&x->x_obj, &s_float); + return (x); +} + +static void slist_ff(t_slist *x) +{ + slist_release(x->x_c); +} + +static void slist_print(t_slist *x) +{ + t_sitem *t=x->x_c->first; + int i=0; + + while(t){ + post("item %d: %s",++i,t->s->s_name); + t=t->next; + } +} + +static void slist_reset(t_slist *x) +{ + scommon_reset(x->x_c); +} + +static void slist_add(t_slist *x,t_symbol *s) +{ + scommon_add(x->x_c,s); +} + +static void slist_find(t_slist *x,t_symbol *s) +{ + outlet_float(x->x_obj.ob_outlet,scommon_find(x->x_c,s)); +} + +static void slist_setlist(t_slist *x,t_symbol *s) +{ + slist_release(x->x_c); + x->x_c = slist_get(s); +} + +static void slist_float(t_slist *x, t_float f) +{ + t_sitem *t=x->x_c->first; + int i=0; + + if(!f) return; + + while(t&&((++i)!=f)){ + t=t->next; + } + + if(t) outlet_symbol(x->x_symout,t->s); +} + +static void slist_len(t_slist *x) +{ + t_sitem *t=x->x_c->first; + int i=0; + + while(t){ + t=t->next; + i++; + } + + outlet_float(x->x_lenout,i); +} + + +void slist_setup(void) +{ + slist_class = class_new(gensym("slist"), (t_newmethod)slist_new, + (t_method)slist_ff, + sizeof(t_slist), 0, A_DEFSYM, 0); + + //class_addbang(slist_class, slist_bang); + class_addfloat(slist_class, slist_float); + class_addmethod(slist_class,(t_method)slist_add, gensym("add"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_find, gensym("find"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_setlist, gensym("setlist"),A_SYMBOL,0); + class_addmethod(slist_class,(t_method)slist_reset, gensym("reset"),0); + class_addmethod(slist_class,(t_method)slist_print, gensym("print"),0); + class_addmethod(slist_class,(t_method)slist_len, gensym("len"),0); + scommon_class = class_new(gensym("slist"), 0, 0, + sizeof(t_scommon), CLASS_PD, 0); +} + diff --git a/ssaw~.c b/ssaw~.c new file mode 100644 index 0000000..07454ef --- /dev/null +++ b/ssaw~.c @@ -0,0 +1,213 @@ +/* +Copyright (C) 2004 Antoine Rousseau +all material Copyright (c) 1997-1999 Miller Puckette. + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* a "sweet" saw generator, as described in pddoc/3.audio/K05.bandlimited .*/ + +#include "m_pd.h" +#include "math.h" +#include + +#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ + + /* machine-dependent definitions. These ifdefs really + should have been by CPU type and not by operating system! */ +#ifdef IRIX + /* big-endian. Most significant byte is at low address in memory */ +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 long /* a data type that has 32 bits */ +#else +#ifdef MSW + /* little-endian; most significant byte is at highest address */ +#define HIOFFSET 1 +#define LOWOFFSET 0 +#define int32 long +#else +#ifdef __FreeBSD__ +#include +#if BYTE_ORDER == LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* BYTE_ORDER */ +#include +#define int32 int32_t +#endif +#ifdef __linux__ + +#include + +#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) +#error No byte order defined +#endif + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define HIOFFSET 1 +#define LOWOFFSET 0 +#else +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#endif /* __BYTE_ORDER */ + +#include +#define int32 int32_t + +#else +#ifdef MACOSX +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 int /* a data type that has 32 bits */ + +#endif /* MACOSX */ +#endif /* __linux__ */ +#endif /* MSW */ +#endif /* SGI */ + +union tabfudge +{ + double tf_d; + int32 tf_i[2]; +}; + + +/* -------------------------- ssaw~ ------------------------------ */ +static t_class *ssaw_class, *scalarssaw_class; +static float ssaw_array[1002]; +#define SAW_ARRAY_LEN 1002 + +typedef struct _ssaw +{ + t_object x_obj; + //from phasor~: + double x_phase; + float x_conv; + float x_f; /* scalar frequency */ + float x_band; /* band limit (Hertz)*/ +} t_ssaw; + +static void *ssaw_new(t_floatarg f) +{ + t_ssaw *x = (t_ssaw *)pd_new(ssaw_class); + x->x_f = f; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + x->x_band = 22000; + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *ssaw_perform(t_int *w) +{ + t_ssaw *x = (t_ssaw *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int i,n = (int)(w[4]); + double dphase = x->x_phase + UNITBIT32; + union tabfudge tf; + int normhipart; + float conv = x->x_conv; + float band=x->x_band*.33; + float *buf = ssaw_array; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase; + + for (i = 0; i < n; i++) + //while (n--) + { + float phase,band2,findex /*= *in++*/; + int index /*= findex*/; + float frac, a, b, c, d, cminusb, *fp; + + tf.tf_i[HIOFFSET] = normhipart; + band2=abs(*in); + if(band2>999999) band2=999999; else if(band2<1) band2=1; + band2=band/band2; + dphase += *in++ * conv; + /**out++*/phase = (tf.tf_d - UNITBIT32)-0.5; + tf.tf_d = dphase; + + findex=phase*band2; + if(findex>0.5) findex=0.5; else if(findex<-0.5) findex=-0.5; + + /*findex=findex*1000+501; + index=findex;*/ + /*if (index < 1) + index = 1, frac = 0; + else if (index > maxindex) + index = maxindex, frac = 1; + else*/ frac = findex - index; + /*fp = buf + index; + a = fp[-1]; + b = fp[0]; + c = fp[1]; + d = fp[2]; + cminusb = c-b; + *out++ = 0.5+ phase - ( + b + frac * ( cminusb - 0.1666667f * (1.-frac) * ( + (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b))) + );*/ + *out++ = 0.5+ phase - buf[(int)(findex*1000+501)]; + } + + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32; + return (w+5); +} + +static void ssaw_dsp(t_ssaw *x, t_signal **sp) +{ + x->x_conv = 1./sp[0]->s_sr; + dsp_add(ssaw_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void ssaw_ft1(t_ssaw *x, t_float f) +{ + x->x_phase = f; +} + +static void ssaw_initarray(void) +{ + int i; + float j; + + for(i=0;i<1002;i++){ + j=(i-1)*M_PI/1000.0; //period 2000 sample, 1 sample back phase + ssaw_array[i]= 0.57692* + (-1*cos(j) + 0.333333*cos(j*3.0) -0.2* cos(j*5.0)); + } +} + +void ssaw_tilde_setup(void) +{ + ssaw_class = class_new(gensym("ssaw~"), (t_newmethod)ssaw_new, 0, + sizeof(t_ssaw), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(ssaw_class, t_ssaw, x_f); + class_addmethod(ssaw_class, (t_method)ssaw_dsp, gensym("dsp"), 0); + class_addmethod(ssaw_class, (t_method)ssaw_ft1, + gensym("ft1"), A_FLOAT, 0); + ssaw_initarray(); + +} + diff --git a/tabdump2.c b/tabdump2.c new file mode 100644 index 0000000..9c779e9 --- /dev/null +++ b/tabdump2.c @@ -0,0 +1,120 @@ +/* +Copyright (C) 2004 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +/* + tabdump2 -- from tabdump (from zexy) but with min/max dumping limits. +*/ + +#include + +static t_class *tabdump_class; + +typedef struct _tabdump +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabdump; + +static void tabdump_bang(t_tabdump *x, t_float findex) +{ + t_garray *A; + int npoints; + t_float *vec; + + if (!(A = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(A, &npoints, &vec)) + error("%s: bad template for tabdump", x->x_arrayname->s_name); + else + { + int n; + t_atom *atombuf = (t_atom *)getbytes(sizeof(t_atom)*npoints); + + for (n = 0; n < npoints; n++) SETFLOAT(&atombuf[n], vec[n]); + outlet_list(x->x_obj.ob_outlet, &s_list, npoints, atombuf); + } +} + + +static void tabdump_dump(t_tabdump *x, t_float min, t_float max) +{ + t_garray *A; + int npoints,nmin=(int)min,nmax=(int)max; + t_float *vec; + + if (!(A = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(A, &npoints, &vec)) + error("%s: bad template for tabdump", x->x_arrayname->s_name); + else if ((min<0)||(max<=min)||(max>npoints)) + error("tabdump: bad arguments min=%d max=%d for %s (%d elements)", + nmin,nmax,x->x_arrayname->s_name,npoints); + else + { + int n; + t_atom *atombuf; + + npoints=nmax-nmin; + atombuf = (t_atom *)getbytes(sizeof(t_atom)*npoints); + + for (n = 0; n < npoints; n++) SETFLOAT(&atombuf[n], vec[n+nmin]); + outlet_list(x->x_obj.ob_outlet, &s_list, npoints, atombuf); + } +} + + +static void tabdump_set(t_tabdump *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabdump_new(t_symbol *s) +{ + t_tabdump *x = (t_tabdump *)pd_new(tabdump_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_list); + + return (x); +} + +static void tabdump_helper(void) +{ + post("\n tabdump2 - object : dumps a table as a package of floats"); + post("'set '\t: read out another table\n" + "'bang'\t\t: dump the table\n" + "'dump '\t\t: dump the table from to (without )\n" + "outlet\t\t: table-data as package of floats"); + post("creation\t: \"tabdump2
\""); + +} + +void tabdump2_setup(void) +{ + tabdump_class = class_new(gensym("tabdump2"), (t_newmethod)tabdump_new, + 0, sizeof(t_tabdump), 0, A_DEFSYM, 0); + class_addbang(tabdump_class, (t_method)tabdump_bang); + class_addmethod(tabdump_class, (t_method)tabdump_dump,gensym("dump"), + A_FLOAT,A_FLOAT); + class_addmethod(tabdump_class, (t_method)tabdump_set, gensym("set"), + A_SYMBOL, 0); + + class_addmethod(tabdump_class, (t_method)tabdump_helper, gensym("help"), 0); + +} + diff --git a/tabenv.c b/tabenv.c new file mode 100644 index 0000000..9b52fbe --- /dev/null +++ b/tabenv.c @@ -0,0 +1,294 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabenv - table envelope computer. ----------------- */ +/*------- (in fact it's a mix between env~ and tabplay~)----------------*/ + +#define MAXOVERLAP 10 +#define MAXVSTAKEN 64 + +typedef struct tabenv +{ + /*env part*/ + t_object x_obj; /* header */ + t_outlet *x_outlet; /* a "float" outlet */ + t_clock *x_clock; /* a "clock" object */ + float *x_buf; /* a Hanning window */ + int x_phase; /* number of points since last output */ + int x_period; /* requested period of output */ + int x_realperiod; /* period rounded up to vecsize multiple */ + int x_npoints; /* analysis window size in samples */ + float x_result; /* result to output */ + float x_sumbuf[MAXOVERLAP]; /* summing buffer */ + float x_f; + + /*tabplay part*/ + int x_tabphase; + int x_nsampsintab; + int x_limit; + float *x_vec; + t_symbol *x_arrayname; +} t_tabenv; + +t_class *tabenv_class; +static void tabenv_tick(t_tabenv *x); + +static void *tabenv_new(t_symbol *s,t_floatarg fnpoints, t_floatarg fperiod) +{ + int npoints = fnpoints; + int period = fperiod; + t_tabenv *x; + float *buf; + int i; + + if (npoints < 1) npoints = 1024; + if (period < 1) period = npoints/2; + if (period < npoints / MAXOVERLAP + 1) + period = npoints / MAXOVERLAP + 1; + if (!(buf = getbytes(sizeof(float) * (npoints + MAXVSTAKEN)))) + { + error("env: couldn't allocate buffer"); + return (0); + } + x = (t_tabenv *)pd_new(tabenv_class); + x->x_buf = buf; + x->x_npoints = npoints; + x->x_phase = 0; + x->x_period = period; + for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; + for (i = 0; i < npoints; i++) + buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints; + for (; i < npoints+MAXVSTAKEN; i++) buf[i] = 0; + x->x_clock = clock_new(x, (t_method)tabenv_tick); + x->x_outlet = outlet_new(&x->x_obj, gensym("float")); + x->x_f = 0; + + /* tabplay */ + x->x_tabphase = 0x7fffffff; + x->x_limit = 0; + x->x_arrayname = s; + + return (x); +} + +static t_int *sigenv_perform(t_int *w) +{ + t_tabenv *x = (t_tabenv *)(w[1]); + t_float *in = (t_float *)(w[2]); + int n = (int)(w[3]); + int count; + float *sump; + in += n; + for (count = x->x_phase, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + { + float *hp = x->x_buf + count; + float *fp = in; + float sum = *sump; + int i; + + for (i = 0; i < n; i++) + { + fp--; + sum += *hp++ * (*fp * *fp); + } + *sump = sum; + } + sump[0] = 0; + x->x_phase -= n; + if (x->x_phase < 0) + { + x->x_result = x->x_sumbuf[0]; + for (count = x->x_realperiod, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + sump[0] = sump[1]; + sump[0] = 0; + x->x_phase = x->x_realperiod - n; + clock_delay(x->x_clock, 0L); + } + return (w+4); +} + +static t_int *tabplay_tilde_perform(t_int *w) +{ + t_tabenv *x = (t_tabenv *)(w[1]); + t_float *out = (t_float *)(w[2]), *fp; + int n = (int)(w[3]), phase = x->x_phase, + endphase = (x->x_nsampsintab < x->x_limit ? + x->x_nsampsintab : x->x_limit), nxfer, n3; + if (!x->x_vec || phase >= endphase) + goto zero; + + nxfer = endphase - phase; + fp = x->x_vec + phase; + if (nxfer > n) + nxfer = n; + n3 = n - nxfer; + phase += nxfer; + while (nxfer--) + *out++ = *fp++; + if (phase >= endphase) + { + clock_delay(x->x_clock, 0); + x->x_phase = 0x7fffffff; + while (n3--) + *out++ = 0; + } + else x->x_phase = phase; + + return (w+4); +zero: + while (n--) *out++ = 0; + return (w+4); +} + + +static void tabenv_perform_64(t_tabenv *x,t_float *in) +{ + int n = 64; + int count; + float *sump; + in += n; + for (count = x->x_phase, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + { + float *hp = x->x_buf + count; + float *fp = in; + float sum = *sump; + int i; + + for (i = 0; i < n; i++) + { + fp--; + sum += *hp++ * (*fp * *fp); + } + *sump = sum; + } + sump[0] = 0; + x->x_phase -= n; + if (x->x_phase < 0) + { + x->x_result = x->x_sumbuf[0]; + for (count = x->x_realperiod, sump = x->x_sumbuf; + count < x->x_npoints; count += x->x_realperiod, sump++) + sump[0] = sump[1]; + sump[0] = 0; + x->x_phase = x->x_realperiod - n; + /*clock_delay(x->x_clock, 0L);*/ + outlet_float(x->x_outlet, powtodb(x->x_result)); + } +} + + +static void tabenv_set(t_tabenv *x, t_symbol *s) +{ + t_garray *a; + + x->x_arrayname = s; + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + { + if (*s->s_name) pd_error(x, "tabenv: %s: no such array", + x->x_arrayname->s_name); + x->x_vec = 0; + } + else if (!garray_getfloatarray(a, &x->x_nsampsintab, &x->x_vec)) + { + error("%s: bad template for tabenv", x->x_arrayname->s_name); + x->x_vec = 0; + } + else garray_usedindsp(a); +} + +static void sigenv_dsp(t_tabenv *x, t_signal **sp) +{ + if (x->x_period % sp[0]->s_n) x->x_realperiod = + x->x_period + sp[0]->s_n - (x->x_period % sp[0]->s_n); + else x->x_realperiod = x->x_period; + dsp_add(sigenv_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + if (sp[0]->s_n > MAXVSTAKEN) bug("sigenv_dsp"); +} + +static void tabenv_list(t_tabenv *x, t_symbol *s, + int argc, t_atom *argv) +{ + long start = atom_getfloatarg(0, argc, argv); + long length = atom_getfloatarg(1, argc, argv); + float *limitp,*p; + int i; + + tabenv_set(x, x->x_arrayname); + + if (start < 0) start = 0; + if (length <= 0) + x->x_limit = 0x7fffffff; + else + x->x_limit = start + length; + x->x_tabphase = start; + + if(length <= 0) length = x->x_nsampsintab - 1; + if(start >= x->x_nsampsintab) start = x->x_nsampsintab - 1; + if((start + length) >= x->x_nsampsintab) + length = x->x_nsampsintab - 1 - start; + + limitp = x->x_vec + start + length - 63; + /*limitp = x->x_vec + 2048;*/ + /*if (x->x_period % length) x->x_realperiod = + x->x_period + length - (x->x_period % length); + else*/ x->x_realperiod = x->x_period; + + for(p = x->x_vec + start; p < limitp ; p += 64) + tabenv_perform_64( x , p ); +} + +static void tabenv_reset(t_tabenv *x) +{ + int i; + x->x_phase = 0; + for (i = 0; i < MAXOVERLAP; i++) x->x_sumbuf[i] = 0; +} + +static void tabenv_tick(t_tabenv *x) /* callback function for the env clock */ +{ + outlet_float(x->x_outlet, powtodb(x->x_result)); +} + +static void tabenv_ff(t_tabenv *x) /* cleanup on free */ +{ + clock_free(x->x_clock); + freebytes(x->x_buf, (x->x_npoints + MAXVSTAKEN) * sizeof(float)); +} + + +void tabenv_setup(void ) +{ + tabenv_class = class_new(gensym("tabenv"), (t_newmethod)tabenv_new, + (t_method)tabenv_ff, sizeof(t_tabenv), 0, A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(tabenv_class, t_tabenv, x_f); + class_addmethod(tabenv_class, (t_method)tabenv_reset, + gensym("reset"), 0); + class_addmethod(tabenv_class, (t_method)tabenv_set, + gensym("set"), A_DEFSYM, 0); + class_addlist(tabenv_class, tabenv_list); + +} + diff --git a/tabreadl.c b/tabreadl.c new file mode 100644 index 0000000..e669bd8 --- /dev/null +++ b/tabreadl.c @@ -0,0 +1,84 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + +/* ---------- tabreadl: control, linear interpolating ------------------------ */ + +static t_class *tabreadl_class; + +typedef struct _tabreadl +{ + t_object x_obj; + t_symbol *x_arrayname; +} t_tabreadl; + +static void tabreadl_float(t_tabreadl *x, t_float f) +{ + t_garray *a; + int npoints; + t_float *vec; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) + error("%s: no such array", x->x_arrayname->s_name); + else if (!garray_getfloatarray(a, &npoints, &vec)) + error("%s: bad template for tabreadl", x->x_arrayname->s_name); + else + { + int n ; + float r,v; + + if (f < 0) f = 0; + else if (f >= npoints) f = npoints - 1; + n=f; + if(npoints>1){ + r=f-n; + v=vec[n]*(1-r)+vec[n+1]*r; + outlet_float(x->x_obj.ob_outlet, v ); + } + else + outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n] : 0)); + } +} + +static void tabreadl_set(t_tabreadl *x, t_symbol *s) +{ + x->x_arrayname = s; +} + +static void *tabreadl_new(t_symbol *s) +{ + t_tabreadl *x = (t_tabreadl *)pd_new(tabreadl_class); + x->x_arrayname = s; + outlet_new(&x->x_obj, &s_float); + return (x); +} + +void tabreadl_setup(void) +{ + tabreadl_class = class_new(gensym("tabreadl"), (t_newmethod)tabreadl_new, + 0, sizeof(t_tabreadl), 0, A_DEFSYM, 0); + class_addfloat(tabreadl_class, (t_method)tabreadl_float); + class_addmethod(tabreadl_class, (t_method)tabreadl_set, gensym("set"), + A_SYMBOL, 0); + +} + + diff --git a/tabsort.c b/tabsort.c new file mode 100644 index 0000000..ec8fcf0 --- /dev/null +++ b/tabsort.c @@ -0,0 +1,124 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabsort - sort a table to a table ----------------- */ + + +typedef struct tabsort +{ + /*env part*/ + t_object x_obj; /* header */ + t_symbol *x_arrayname1; + t_symbol *x_arrayname2; +} t_tabsort; + +t_class *tabsort_class; + +static void *tabsort_new(t_symbol *tab1,t_symbol *tab2) +{ + t_tabsort *x; + x = (t_tabsort *)pd_new(tabsort_class); + + x->x_arrayname1 = tab1; + x->x_arrayname2 = tab2; + outlet_new((t_object*)x, &s_bang); + + return (x); +} + +static void tabsort_set1(t_tabsort *x, t_symbol *s) +{ + x->x_arrayname1 = s; +} +static void tabsort_set2(t_tabsort *x, t_symbol *s) +{ + x->x_arrayname2 = s; +} + +static void tabsort_float(t_tabsort *x, t_floatarg n) +{ + t_garray *a; + int n1,n2,i,j; + float *vec1,*vec2,tmp; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname1, garray_class))) + { + if (*x->x_arrayname1->s_name) pd_error(x, "tabsort: %s: no such array", + x->x_arrayname1->s_name); + return; + } + else if (!garray_getfloatarray(a, &n1, &vec1)) + { + error("%s: bad template for tabsort", x->x_arrayname1->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname2, garray_class))) + { + if (*x->x_arrayname2->s_name) pd_error(x, "tabsort: %s: no such array", + x->x_arrayname2->s_name); + return; + } + else if (!garray_getfloatarray(a, &n2, &vec2)) + { + error("%s: bad template for tabsort", x->x_arrayname2->s_name); + return; + } + + if(n>n1) n=n1; + if(n>n2) n=n2; + + + for(i=0;ii;j--) + if(vec1[(int)vec2[j-1]]ob_outlet); +} + + +static void tabsort_ff(t_tabsort *x) /* cleanup on free */ +{ +} + + +void tabsort_setup(void ) +{ + tabsort_class = class_new(gensym("tabsort"), (t_newmethod)tabsort_new, + (t_method)tabsort_ff, sizeof(t_tabsort), 0, A_DEFSYM, A_DEFSYM, 0); + class_addmethod(tabsort_class, (t_method)tabsort_set1, + gensym("set1"), A_DEFSYM, 0); + class_addmethod(tabsort_class, (t_method)tabsort_set2, + gensym("set2"), A_DEFSYM, 0); + class_addfloat(tabsort_class, tabsort_float); + +} + diff --git a/tabsort2.c b/tabsort2.c new file mode 100644 index 0000000..63d0fd6 --- /dev/null +++ b/tabsort2.c @@ -0,0 +1,164 @@ +/* +Copyright (C) 2002 Antoine Rousseau + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "m_pd.h" +#include "math.h" + + +/* ---------------- tabsort2 - sort a table to a table ----------------- */ + + +typedef struct tabsort2 +{ + t_object x_obj; /* header */ + t_symbol *x_arrayname1; + t_symbol *x_arrayname2; + t_symbol *x_arrayname3; + t_clock *x_clock; /* a "clock" object */ +} t_tabsort2; + +t_class *tabsort2_class; + +static void tabsort2_tick(t_tabsort2 *x); + +static void *tabsort2_new(t_symbol *tab1,t_symbol *tab2,t_symbol *tab3) +{ + t_tabsort2 *x; + x = (t_tabsort2 *)pd_new(tabsort2_class); + + x->x_arrayname1 = tab1; + x->x_arrayname2 = tab2; + x->x_arrayname3 = tab3; + x->x_clock = clock_new(x, (t_method)tabsort2_tick); + outlet_new((t_object*)x, &s_float); + + return (x); +} + +static void tabsort2_set1(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname1 = s; +} +static void tabsort2_set2(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname2 = s; +} + +static void tabsort2_set3(t_tabsort2 *x, t_symbol *s) +{ + x->x_arrayname3 = s; +} + +static void tabsort2_float(t_tabsort2 *x, t_floatarg n) +{ + t_garray *a; + int n1,n2,n3,i,j,h,sqn; + float *vec1,*vec2,*vec3,tmp; + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname1, garray_class))) + { + if (*x->x_arrayname1->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname1->s_name); + return; + } + else if (!garray_getfloatarray(a, &n1, &vec1)) + { + error("%s: bad template for tabsort2", x->x_arrayname1->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname2, garray_class))) + { + if (*x->x_arrayname2->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname2->s_name); + return; + } + else if (!garray_getfloatarray(a, &n2, &vec2)) + { + error("%s: bad template for tabsort2", x->x_arrayname2->s_name); + return; + } + + if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname3, garray_class))) + { + if (*x->x_arrayname3->s_name) pd_error(x, "tabsort2: %s: no such array", + x->x_arrayname3->s_name); + return; + } + else if (!garray_getfloatarray(a, &n3, &vec3)) + { + error("%s: bad template for tabsort2", x->x_arrayname3->s_name); + return; + } + + if(n>n1) n=n1; + if(n>n2) n=n2; + if(n>n3) n=n3; + + for(i=0;ii;j--) + if(vec1[(int)vec3[j-1]]i;j--) + if(vec2[(int)vec3[h*sqn+j-1]]ob_outlet,(float)sqn); +} + +static void tabsort2_tick(t_tabsort2 *x) /* callback function for the env clock */ +{ + + //clock_delay(x->x_clock, 0L); +} + +static void tabsort2_ff(t_tabsort2 *x) /* cleanup on free */ +{ + clock_free(x->x_clock); +} + + +void tabsort2_setup(void ) +{ + tabsort2_class = class_new(gensym("tabsort2"), (t_newmethod)tabsort2_new, + (t_method)tabsort2_ff, sizeof(t_tabsort2), 0, A_DEFSYM, A_DEFSYM, A_DEFSYM, 0); + class_addmethod(tabsort2_class, (t_method)tabsort2_set1, + gensym("set1"), A_DEFSYM, 0); + class_addmethod(tabsort2_class, (t_method)tabsort2_set2, + gensym("set2"), A_DEFSYM, 0); + class_addfloat(tabsort2_class, tabsort2_float); + +} + diff --git a/wac.c b/wac.c new file mode 100644 index 0000000..1bf132e --- /dev/null +++ b/wac.c @@ -0,0 +1,253 @@ + /* + wacom graphire on serial port only... +*/ + +#include + +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 256 +#define HEADER_BIT 0x80 +#define ZAXIS_SIGN_BIT 0x40 +#define ZAXIS_BIT 0x04 +#define ZAXIS_BITS 0x3f +#define POINTER_BIT 0x20 +#define PROXIMITY_BIT 0x40 +#define BUTTON_FLAG 0x08 +#define BUTTONS_BITS 0x78 +#define TILT_SIGN_BIT 0x40 +#define TILT_BITS 0x3f + +/* defines to discriminate second side button and the eraser */ +#define ERASER_PROX 4 +#define OTHER_PROX 1 + +#define Threshold 1000 +unsigned char data[7]; + +typedef struct _wac +{ + t_object t_ob; + t_outlet *axis_out; + t_outlet *button_out; + t_symbol *file; + int fd; + int count; + int oldbuttons; + unsigned char data[BUFSIZE]; +}t_wac; + +t_class *wac_class; + +void wac_setup(void); +static void wac_read(t_wac *x,int fd); +static void wac_process(t_wac *x); + +static void wac_open(t_wac *x) +{ + if(x->fd>=0) return; + + x->fd = open (x->file->s_name, O_RDONLY | O_NONBLOCK); + if(x->fd<0){ + post("open (%s, O_RDONLY | O_NONBLOCK)",x->file->s_name); + perror("open"); + return; + } + sys_addpollfn(x->fd,(t_fdpollfn)wac_read,(void*)x); +} + +static void wac_close(t_wac *x) +{ + if(x->fd<0) return; + + sys_rmpollfn(x->fd); + close(x->fd); + x->fd=-1; +} + +static void wac_float(t_wac *x,t_floatarg connect) +{ + if(connect!=0) wac_open(x); + else wac_close(x); +} + +static void *wac_new(t_symbol *file) +{ + t_wac *x = (t_wac *)pd_new(wac_class); + + //if(file->s_name) + if(file!=&s_) + x->file=file; + else x->file=gensym("/dev/ttyS0"); + + post("wac_new file=%s",x->file->s_name); + x->axis_out = outlet_new(&x->t_ob, &s_list); + x->button_out = outlet_new(&x->t_ob, &s_list); + + x->fd=-1; + + return (void *)x; +} + +void wac_setup(void) +{ + wac_class = class_new(gensym("wac"),(t_newmethod)wac_new, + (t_method)wac_close, sizeof(t_wac), 0, A_DEFSYM, 0); + class_addfloat(wac_class, wac_float); + + +} + + +static void wac_read(t_wac *x,int fd) +{ + int len,i=0; + unsigned char b; + unsigned char buffer[BUFSIZE]; + + while((len=read(fd,buffer,BUFSIZE))> -1){ + + for(i=0;icount=0; + x->data[x->count++]=buffer[i]; + if(x->count==7) wac_process(x); + } + } +} + +static void wac_process(t_wac *X) +{ + int is_stylus = 1, is_button, is_proximity, wheel=0; + int x, y, z, buttons, tx = 0, ty = 0; + unsigned char *data=X->data; + t_atom ats[3]; + + is_stylus = (data[0] & POINTER_BIT); + + if(!is_stylus) return; + + x = (((data[0] & 0x3) << 14) + + (data[1] << 7) + + data[2]); + y = (((data[3] & 0x3) << 14) + + (data[4] << 7) + + data[5]); + + + z = ((data[6] & ZAXIS_BITS) * 2) + + ((data[3] & ZAXIS_BIT) >> 2); + + //z = z*4 + ((data[0] & ZAXIS_BIT) >> 1); + + if (!(data[6] & ZAXIS_SIGN_BIT)) { + z += 128; + } + + is_proximity = (data[0] & PROXIMITY_BIT); + + buttons = ((data[3] & 0x38) >> 3); + /*if (is_stylus) { + buttons = ((data[3] & 0x30) >> 3) | + (z >= Threshold ? 1 : 0); + } + else { + buttons = (data[3] & 0x38) >> 3; + + wheel = (data[6] & 0x30) >> 4; + + if (data[6] & 0x40) { + wheel = -wheel; + } + }*/ + //is_button = (buttons != 0); + if(buttons!=X->oldbuttons) + { + X->oldbuttons=buttons; + + SETFLOAT(&ats[0],buttons&1); + SETFLOAT(&ats[1],(buttons&2)!=0); + SETFLOAT(&ats[2],(buttons&4)!=0); + outlet_list(X->button_out,0,3,ats); + } + SETFLOAT(&ats[0],x/5103.0); + SETFLOAT(&ats[1],y/3711.0); + SETFLOAT(&ats[2],z/256.0); + outlet_list(X->axis_out,0,3,ats); +} + /* Format of 7 bytes data packet for Wacom Tablets + Byte 1 + bit 7 Sync bit always 1 + bit 6 Pointing device detected + bit 5 Cursor = 0 / Stylus = 1 + bit 4 Reserved + bit 3 1 if a button on the pointing device has been pressed + bit 2 Reserved + bit 1 X15 + bit 0 X14 + + Byte 2 + bit 7 Always 0 + bits 6-0 = X13 - X7 + + Byte 3 + bit 7 Always 0 + bits 6-0 = X6 - X0 + + Byte 4 + bit 7 Always 0 + bit 6 B3 + bit 5 B2 + bit 4 B1 + bit 3 B0 + bit 2 P0 + bit 1 Y15 + bit 0 Y14 + + Byte 5 + bit 7 Always 0 + bits 6-0 = Y13 - Y7 + + Byte 6 + bit 7 Always 0 + bits 6-0 = Y6 - Y0 + + Byte 7 + bit 7 Always 0 + bit 6 Sign of pressure data + bit 5 P6 + bit 4 P5 + bit 3 P4 + bit 2 P3 + bit 1 P2 + bit 0 P1 + + byte 8 and 9 are optional and present only + in tilt mode. + + Byte 8 + bit 7 Always 0 + bit 6 Sign of tilt X + bit 5 Xt6 + bit 4 Xt5 + bit 3 Xt4 + bit 2 Xt3 + bit 1 Xt2 + bit 0 Xt1 + + Byte 9 + bit 7 Always 0 + bit 6 Sign of tilt Y + bit 5 Yt6 + bit 4 Yt5 + bit 3 Yt4 + bit 2 Yt3 + bit 1 Yt2 + bit 0 Yt1 + + */ + -- cgit v1.2.1