diff options
322 files changed, 38287 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..34ee839 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,31 @@ +This software is copyrighted by Miller Puckette and others. The following +terms apply to all files associated with the software unless explicitly +disclaimed in individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +RESTRICTED RIGHTS: Use, duplication or disclosure by the government +is subject to the restrictions as set forth in subparagraph (c) (1) (ii) +of the Rights in Technical Data and Computer Software Clause as DFARS +252.227-7013 and FAR 52.227-19. diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 0000000..3db7717 --- /dev/null +++ b/Makefile.common @@ -0,0 +1,285 @@ +# next line has to be edited manually +PD_DIR = $(ROOT_DIR)/../pd/src + +OS_NAME = $(shell uname -s) +ifneq ($(OS_NAME),Linux) +ifneq ($(OS_NAME),Darwin) +# FIXME +endif +endif + +TILDE = ~ + +-include Makefile.dirs +include Makefile.sources +include Makefile.objects + +CC = gcc + +default: define_build all + +SHARED_DIR = $(ROOT_DIR)/shared +OBJ_DIR = . +OUT_DIR = $(ROOT_DIR)/bin + +BASE_DIR = $(shell basename `pwd`) +BASE_NAME = $(shell basename `pwd` | awk -F - '{print $$1}') + +# CX: control external's main file +# AX: audio (tilde) external's main file +# LX: symlink external's main file +# (if symlink external is tilde-only, use OTHER_SOURCES and AX_CLASSES) + +CX_NAMES = $(notdir $(CX_SOURCES)) +AX_NAMES = $(notdir $(AX_SOURCES)) +LX_NAMES = $(notdir $(LX_SOURCES)) +TYPES_NAMES = $(notdir $($1_SOURCES)) + +CX_DIR = $(dir $(firstword $(CX_SOURCES))) +AX_DIR = $(dir $(firstword $(AX_SOURCES))) +TYPES_DIR = $(dir $(firstword $($1_SOURCES))) + +TYPES_EXTERNS = \ + $(patsubst %.c,%$($1_TILDE).$(X_SUFFIX),$(call TYPES_NAMES,$1)) + +SOURCES = $(CX_SOURCES) $(AX_SOURCES) $(LX_SOURCES) $(OTHER_SOURCES) \ + $(foreach type,$(TYPES),$($(type)_SOURCES)) + +INCLUDES = -I. -I$(PD_DIR) -I$(SHARED_DIR) + +ifeq ($(OS_NAME),Linux) +X_SUFFIX = pd_linux +DEFINES = -DUNIX +OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer +LFLAGS = -export_dynamic -shared +endif + +ifeq ($(OS_NAME),Darwin) +X_SUFFIX = pd_darwin +DEFINES = -DUNIX -DMACOSX +OPT_CFLAGS = -O2 -funroll-loops -fomit-frame-pointer +# -private_bundle is a guess, LATER check this +LFLAGS = -bundle -undefined suppress -flat_namespace +endif + +WARN_CFLAGS = -Wall -W -Wstrict-prototypes -Werror \ + -Wno-unused -Wno-parentheses -Wno-switch +DBG_CFLAGS = +CFLAGS = $(WARN_CFLAGS) $(OPT_CFLAGS) $(DEFINES) $(INCLUDES) + +EXTERNS = $(foreach fn,$(CX_NAMES:.c=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ + $(foreach fn,$(AX_NAMES:.c=~.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ + $(foreach fn,$(LX_SOURCES:.c=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ + $(foreach fn,$(CX_CLASSES:=.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ + $(foreach fn,$(AX_CLASSES:=~.$(X_SUFFIX)),$(OUT_DIR)/$(fn)) \ + $(foreach type,$(TYPES),\ + $(foreach fn,$(call TYPES_EXTERNS,$(type)),$(OUT_DIR)/$(fn))) + +TYPES_RULE = $(foreach fn,$(call TYPES_EXTERNS,$1),$(OUT_DIR)/$(fn)): \ + $(OUT_DIR)/%$($1_TILDE).$(X_SUFFIX) \ + : $(call TYPES_DIR,$1)%.o $($1_PRIVATEOBJECTS) \ + $(foreach obj,$($1_OBJECTS),$(SHARED_DIR)/$(obj)) \ + ; $(CC) -o $$@ $(CFLAGS) $(LFLAGS) $$+ + +# LATER find a better way... +$(if $(word 1,$(TYPES)),$(call TYPES_RULE,$(word 1,$(TYPES)))) +$(if $(word 2,$(TYPES)),$(call TYPES_RULE,$(word 2,$(TYPES)))) +$(if $(word 3,$(TYPES)),$(call TYPES_RULE,$(word 3,$(TYPES)))) +$(if $(word 4,$(TYPES)),$(call TYPES_RULE,$(word 4,$(TYPES)))) +$(if $(word 5,$(TYPES)),$(call TYPES_RULE,$(word 5,$(TYPES)))) +$(if $(word 6,$(TYPES)),$(call TYPES_RULE,$(word 6,$(TYPES)))) +$(if $(word 7,$(TYPES)),$(call TYPES_RULE,$(word 7,$(TYPES)))) +$(if $(word 8,$(TYPES)),$(call TYPES_RULE,$(word 8,$(TYPES)))) +$(if $(word 9,$(TYPES)),$(call TYPES_RULE,$(word 9,$(TYPES)))) +$(if $(word 10,$(TYPES)),$(call TYPES_RULE,$(word 10,$(TYPES)))) +$(if $(word 11,$(TYPES)),$(call TYPES_RULE,$(word 11,$(TYPES)))) +$(if $(word 12,$(TYPES)),$(call TYPES_RULE,$(word 12,$(TYPES)))) +$(if $(word 13,$(TYPES)),$(call TYPES_RULE,$(word 13,$(TYPES)))) +$(if $(word 14,$(TYPES)),$(call TYPES_RULE,$(word 14,$(TYPES)))) +$(if $(word 15,$(TYPES)),$(call TYPES_RULE,$(word 15,$(TYPES)))) +$(if $(word 16,$(TYPES)),$(call TYPES_RULE,$(word 16,$(TYPES)))) +$(if $(word 17,$(TYPES)),$(call TYPES_RULE,$(word 17,$(TYPES)))) +$(if $(word 18,$(TYPES)),$(call TYPES_RULE,$(word 18,$(TYPES)))) +$(if $(word 19,$(TYPES)),$(call TYPES_RULE,$(word 19,$(TYPES)))) +$(if $(word 20,$(TYPES)),$(call TYPES_RULE,$(word 20,$(TYPES)))) +$(if $(word 21,$(TYPES)),$(call TYPES_RULE,$(word 21,$(TYPES)))) +$(if $(word 22,$(TYPES)),$(call TYPES_RULE,$(word 22,$(TYPES)))) +$(if $(word 23,$(TYPES)),$(call TYPES_RULE,$(word 23,$(TYPES)))) +$(if $(word 24,$(TYPES)),$(call TYPES_RULE,$(word 24,$(TYPES)))) + +OBJECTS = $(foreach fn,$(OTHER_SOURCES:.c=.o),$(OBJ_DIR)/$(fn)) \ + $(foreach fn,$(LX_SOURCES:.c=.o),$(OBJ_DIR)/$(fn)) \ + $(foreach fn,$(SHARED_OBJECTS),$(SHARED_DIR)/$(fn)) + +# lame... +.PRECIOUS: %.o + +# rules for symlink externals must precede generic extern rules +$(OUT_DIR)/$(BASE_NAME)_%~.$(X_SUFFIX): $(OUT_DIR)/$(BASE_NAME).$(X_SUFFIX) + -ln -sf $(BASE_NAME).$(X_SUFFIX) $@ +$(OUT_DIR)/$(BASE_NAME)_%.$(X_SUFFIX): $(OUT_DIR)/$(BASE_NAME).$(X_SUFFIX) + -ln -sf $(BASE_NAME).$(X_SUFFIX) $@ + +# library stub +# if not equal BASE_NAME, it has to be declared explicitly in BASE_DIR/Makefile +$(OUT_DIR)/$(LX_STUB)_%~.$(X_SUFFIX): $(OUT_DIR)/$(BASE_NAME).$(X_SUFFIX) + -ln -sf $(BASE_NAME).$(X_SUFFIX) $@ +$(OUT_DIR)/$(LX_STUB)_%.$(X_SUFFIX): $(OUT_DIR)/$(BASE_NAME).$(X_SUFFIX) + -ln -sf $(BASE_NAME).$(X_SUFFIX) $@ +$(OUT_DIR)/$(LX_STUB).$(X_SUFFIX): $(OUT_DIR)/$(BASE_NAME).$(X_SUFFIX) + -ln -sf $(BASE_NAME).$(X_SUFFIX) $@ + +# generic rule for audio externals +$(OUT_DIR)/%~.$(X_SUFFIX): $(AX_DIR)%.c $(OBJECTS) + $(CC) -o $@ $(CFLAGS) $(LFLAGS) $(OBJECTS) $< + +# generic rule for control externals +$(OUT_DIR)/%.$(X_SUFFIX): $(CX_DIR)%.c $(OBJECTS) + $(CC) -o $@ $(CFLAGS) $(LFLAGS) $(OBJECTS) $< + +SUBDIRS = @for i in $(MIXED_DIRS) and_in_case_it_is_null ; \ + do ( if [ -d $$i ] ; then \ + cd $$i; $(MAKE) $@ ; fi ) ; done + +SUBDIRS_DEFAULT = @for i in $(MIXED_DIRS) and_in_case_it_is_null ; \ + do ( if [ -d $$i ] ; then \ + cd $$i; $(MAKE) ; fi ) ; done + +define_build: + @if [[ -f build_counter && \ + `date -r build_counter +%j` != `date +%j` ]] ; then \ + mv build_counter build_counter~ ; \ + echo -n 'increment build counter (y/n)? [n]' ; read doit ; \ + if [ $$doit ] && [ $$doit == 'y' ] ; then \ + cat build_counter~ | \ + awk '{if (index($$2,"BUILD")) print $$1, $$2, $$3+1; else print}' \ + > build_counter ; \ + cat build_counter | \ + awk 'BEGIN {printf toupper("$(BASE_NAME)_VERSION = ")} \ + {gsub("\"","",$$3); printf $$3; if (NR==1) printf "-"} \ + END {printf "\r\n" }' > $(ROOT_DIR)/ViCious/$(BASE_DIR)/version ; \ + else cat build_counter~ > build_counter ; fi \ + fi + +all$(BASE_NAME)s.c: Makefile.sources + $(ROOT_DIR)/dumpsetups > $@ + +all: $(EXTERNS) + $(SUBDIRS_DEFAULT) + +clean: emptydeps +# remove all objects and externs that are contained in current directory + -rm -f *.o *.$(X_SUFFIX) + $(SUBDIRS) + +cleanall: clean +# remove default target externs + -rm -f $(EXTERNS) + +OLDROOT_DIR = $(shell ls -d -1 ../../Mixed-* | tail -1) + +diff: + @echo -n > diff.out ; \ + for f in {*.h,*.c} ; do \ + if [ -f $$f ] ; then \ + diff -u $(OLDROOT_DIR)/$(BASE_DIR)/$$f $$f >> diff.out ; \ + fi \ + done + +VERSION = $(shell awk \ + '{if (index($$2,"VERSION")) print substr($$3,2,length($$3)-2)}' \ + build_counter) +RELEASE = $(shell awk \ + '{if (index($$2,"RELEASE")) print substr($$3,2,length($$3)-2)}' \ + build_counter) +BUILD = $(shell awk '{if (index($$2,"BUILD")) print $$3}' build_counter) + +RELEASE_STUB = release/$(BASE_NAME)-$(VERSION)-$(RELEASE)$(BUILD) +SRC_TAR = $(RELEASE_STUB)-src.tar +BIN_TAR = $(RELEASE_STUB)-bin.tar +LIB_TAR = $(RELEASE_STUB)-lib.tar +DOC_TAR = $(RELEASE_STUB)-doc.tar +ALL_TAR = $(RELEASE_STUB)-all.tar +REL_BINDIR = bin + +REL_LIBNAMES = $(foreach fn,$(RELEASE_LIBS:=.$(X_SUFFIX)),$(REL_BINDIR)/$(fn)) + +REL_EXTERNS = $(foreach fn,$(CX_NAMES:.c=.$(X_SUFFIX)),$(REL_BINDIR)/$(fn)) \ + $(foreach fn,$(AX_NAMES:.c=~.$(X_SUFFIX)),$(REL_BINDIR)/$(fn)) \ + $(REL_LIBNAMES) $(REL_BINDIR)/$(RELEASE_APPS) \ + $(foreach type,$(TYPES),\ + $(foreach fn,$(call TYPES_EXTERNS,$(type)),$(REL_BINDIR)/$(fn))) + +REL_ROOTSRC = LICENSE.txt Makefile.common dumpsetups + +srelease: emptydeps define_build + cd $(ROOT_DIR)/shared; $(MAKE) emptydeps + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-all.exclude -cf \ + $(SRC_TAR) $(BASE_DIR)/* $(REL_ROOTSRC) + cd $(ROOT_DIR); tar -T $(BASE_DIR)/$(BASE_NAME)-shared.include -rf \ + $(SRC_TAR) + cd $(ROOT_DIR); gzip -f $(SRC_TAR) + +stestrelease: emptydeps define_build + cd $(ROOT_DIR)/shared; $(MAKE) emptydeps + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-all.exclude -cf \ + $(SRC_TAR) $(BASE_DIR)/* $(REL_ROOTSRC) + cd $(ROOT_DIR); tar -T $(BASE_DIR)/$(BASE_NAME)-shared.include -rf \ + $(SRC_TAR) + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-test.exclude -rf \ + $(SRC_TAR) test/$(BASE_NAME)/* + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-vicious.exclude -rf \ + $(SRC_TAR) ViCious/$(BASE_DIR)/* + cd $(ROOT_DIR); gzip -f $(SRC_TAR) + +brelease: define_build + cd $(ROOT_DIR); tar zcf \ + $(BIN_TAR).gz $(REL_EXTERNS) + +rellibs: + cd $(ROOT_DIR); tar zcf \ + $(LIB_TAR).gz $(REL_LIBNAMES) + +drelease: define_build + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-doc.exclude -zcf \ + $(DOC_TAR).gz doc/examples/$(BASE_NAME)/* + +release: srelease brelease drelease + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-all.exclude -cf \ + $(ALL_TAR) $(BASE_DIR)/* $(REL_ROOTSRC) $(REL_EXTERNS) + cd $(ROOT_DIR); tar -T $(BASE_DIR)/$(BASE_NAME)-shared.include -rf \ + $(ALL_TAR) + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-doc.exclude -rf \ + $(ALL_TAR) doc/examples/$(BASE_NAME)/* + cd $(ROOT_DIR); gzip -f $(ALL_TAR) + +testrelease: stestrelease brelease + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-all.exclude -cf \ + $(ALL_TAR) $(BASE_DIR)/* $(REL_ROOTSRC) $(REL_EXTERNS) + cd $(ROOT_DIR); tar -T $(BASE_DIR)/$(BASE_NAME)-shared.include -rf \ + $(ALL_TAR) + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-test.exclude -rf \ + $(ALL_TAR) test/$(BASE_NAME)/* + cd $(ROOT_DIR); tar -X $(BASE_DIR)/$(BASE_NAME)-vicious.exclude -rf \ + $(ALL_TAR) ViCious/$(BASE_DIR)/* + cd $(ROOT_DIR); gzip -f $(ALL_TAR) + +snap: emptyalldeps testrelease rellibs + +depend: + $(CC) $(CFLAGS) -M $(SOURCES) > Makefile.deps + $(SUBDIRS) + +emptydeps: + -rm -f Makefile.deps + touch Makefile.deps + chmod 666 Makefile.deps + +emptyalldeps: emptydeps + $(SUBDIRS) + +Makefile.deps: + touch Makefile.deps + chmod 666 Makefile.deps + +-include Makefile.deps diff --git a/ViCious/cyclone/sources b/ViCious/cyclone/sources new file mode 100644 index 0000000..cf37233 --- /dev/null +++ b/ViCious/cyclone/sources @@ -0,0 +1,184 @@ +LIB_CYCLONE = \
+ shadow\cyclone.c \
+ shadow\nettles.c \
+ shadow\dummies.c \
+ shared\common\loud.c \
+ shared\common\grow.c \
+ shared\common\binport.c \
+ shared\common\port.c \
+ shared\hammer\file.c \
+ shared\sickle\sic.c \
+ shared\unstable\fragile.c \
+ shared\unstable\loader.c
+
+LIB_HAMMER = \
+ hammer\hammer.c \
+ hammer\allhammers.c \
+ shared\common\loud.c \
+ shared\common\grow.c \
+ shared\common\rand.c \
+ shared\common\vefl.c \
+ shared\common\sq.c \
+ shared\common\bifi.c \
+ shared\common\mifi.c \
+ shared\common\binport.c \
+ shared\common\port.c \
+ shared\hammer\file.c \
+ shared\hammer\gui.c \
+ shared\hammer\tree.c \
+ shared\unstable\fragile.c
+
+ALL_HAMMERS = \
+ hammer\testmess.c \
+ hammer\accum.c \
+ hammer\acos.c \
+ hammer\active.c \
+ hammer\anal.c \
+ hammer\Append.c \
+ hammer\asin.c \
+ hammer\bangbang.c \
+ hammer\bondo.c \
+ hammer\Borax.c \
+ hammer\Bucket.c \
+ hammer\buddy.c \
+ hammer\capture.c \
+ hammer\cartopol.c \
+ hammer\Clip.c \
+ hammer\coll.c \
+ hammer\comment.c \
+ hammer\cosh.c \
+ hammer\counter.c \
+ hammer\cycle.c \
+ hammer\decide.c \
+ hammer\Decode.c \
+ hammer\drunk.c \
+ hammer\flush.c \
+ hammer\forward.c \
+ hammer\fromsymbol.c \
+ hammer\funbuff.c \
+ hammer\funnel.c \
+ hammer\gate.c \
+ hammer\grab.c \
+ hammer\Histo.c \
+ hammer\iter.c \
+ hammer\match.c \
+ hammer\maximum.c \
+ hammer\mean.c \
+ hammer\midiflush.c \
+ hammer\midiformat.c \
+ hammer\midiparse.c \
+ hammer\minimum.c \
+ hammer\mousefilter.c \
+ hammer\MouseState.c \
+ hammer\next.c \
+ hammer\offer.c \
+ hammer\onebang.c \
+ hammer\past.c \
+ hammer\Peak.c \
+ hammer\poltocar.c \
+ hammer\prepend.c \
+ hammer\prob.c \
+ hammer\pv.c \
+ hammer\seq.c \
+ hammer\sinh.c \
+ hammer\speedlim.c \
+ hammer\spell.c \
+ hammer\split.c \
+ hammer\spray.c \
+ hammer\sprintf.c \
+ hammer\substitute.c \
+ hammer\sustain.c \
+ hammer\switch.c \
+ hammer\tanh.c \
+ hammer\thresh.c \
+ hammer\TogEdge.c \
+ hammer\tosymbol.c \
+ hammer\Trough.c \
+ hammer\universal.c \
+ hammer\urn.c \
+ hammer\Uzi.c \
+ hammer\xbendin.c \
+ hammer\xbendin2.c \
+ hammer\xbendout.c \
+ hammer\xbendout2.c \
+ hammer\xnotein.c \
+ hammer\xnoteout.c \
+ hammer\zl.c
+
+LIB_SICKLE = \
+ sickle\sickle.c \
+ sickle\allsickles.c \
+ shared\common\loud.c \
+ shared\common\grow.c \
+ shared\common\vefl.c \
+ shared\common\binport.c \
+ shared\common\port.c \
+ shared\hammer\file.c \
+ shared\sickle\sic.c \
+ shared\sickle\arsic.c \
+ shared\unstable\forky.c \
+ shared\unstable\fragile.c
+
+ALL_SICKLES = \
+ sickle\abs.c \
+ sickle\acos.c \
+ sickle\acosh.c \
+ sickle\allpass.c \
+ sickle\asin.c \
+ sickle\asinh.c \
+ sickle\atan.c \
+ sickle\atan2.c \
+ sickle\atanh.c \
+ sickle\average.c \
+ sickle\avg.c \
+ sickle\bitand.c \
+ sickle\bitnot.c \
+ sickle\bitor.c \
+ sickle\bitshift.c \
+ sickle\bitxor.c \
+ sickle\capture.c \
+ sickle\cartopol.c \
+ sickle\change.c \
+ sickle\click.c \
+ sickle\Clip.c \
+ sickle\comb.c \
+ sickle\cosh.c \
+ sickle\cosx.c \
+ sickle\count.c \
+ sickle\cycle.c \
+ sickle\delay.c \
+ sickle\delta.c \
+ sickle\deltaclip.c \
+ sickle\edge.c \
+ sickle\frameaccum.c \
+ sickle\framedelta.c \
+ sickle\index.c \
+ sickle\kink.c \
+ sickle\Line.c \
+ sickle\linedrive.c \
+ sickle\log.c \
+ sickle\lookup.c \
+ sickle\minmax.c \
+ sickle\peakamp.c \
+ sickle\peek.c \
+ sickle\phasewrap.c \
+ sickle\play.c \
+ sickle\poltocar.c \
+ sickle\pow.c \
+ sickle\rand.c \
+ sickle\rampsmooth.c \
+ sickle\record.c \
+ sickle\sah.c \
+ sickle\Scope.c \
+ sickle\sinh.c \
+ sickle\sinx.c \
+ sickle\slide.c \
+ sickle\Snapshot.c \
+ sickle\spike.c \
+ sickle\tanh.c \
+ sickle\tanx.c \
+ sickle\train.c \
+ sickle\trapezoid.c \
+ sickle\triangle.c \
+ sickle\vectral.c \
+ sickle\wave.c
diff --git a/cyclone/Makefile b/cyclone/Makefile new file mode 100644 index 0000000..fc022be --- /dev/null +++ b/cyclone/Makefile @@ -0,0 +1,2 @@ +ROOT_DIR = .. +include $(ROOT_DIR)/Makefile.common diff --git a/cyclone/Makefile.dirs b/cyclone/Makefile.dirs new file mode 100644 index 0000000..0dde72f --- /dev/null +++ b/cyclone/Makefile.dirs @@ -0,0 +1,2 @@ +MIXED_DIRS = shadow hammer sickle +RELEASE_DIRS = shadow hammer sickle diff --git a/cyclone/Makefile.objects b/cyclone/Makefile.objects new file mode 100644 index 0000000..9b421fe --- /dev/null +++ b/cyclone/Makefile.objects @@ -0,0 +1,24 @@ +HLOUD_OBJECTS = common/loud.o +HFRAGILE_OBJECTS = common/loud.o unstable/fragile.o +HGROW_OBJECTS = common/grow.o common/loud.o +HFILE_OBJECTS = hammer/file.o common/loud.o +HRAND_OBJECTS = common/rand.o common/loud.o +HRANDFILE_OBJECTS = common/rand.o hammer/file.o common/loud.o +HRANDGROW_OBJECTS = common/rand.o common/grow.o common/loud.o +HTREE_OBJECTS = hammer/tree.o common/loud.o +HTREEFILEVEFL_OBJECTS = hammer/tree.o hammer/file.o \ + common/vefl.o common/loud.o unstable/fragile.o +HGUI_OBJECTS = hammer/gui.o common/loud.o +HSEQ_OBJECTS = common/sq.o common/bifi.o common/mifi.o \ + hammer/file.o common/grow.o common/loud.o +SSIC_OBJECTS = sickle/sic.o common/loud.o +SFORKY_OBJECTS = sickle/sic.o common/loud.o unstable/forky.o +SFRAGILE_OBJECTS = sickle/sic.o common/loud.o unstable/fragile.o +SGROW_OBJECTS = common/grow.o sickle/sic.o common/loud.o +SGROWFORKY_OBJECTS = common/grow.o sickle/sic.o common/loud.o unstable/forky.o +SVEFL_OBJECTS = common/vefl.o sickle/sic.o common/loud.o unstable/fragile.o +SARSIC_OBJECTS = sickle/sic.o sickle/arsic.o common/vefl.o \ + common/loud.o unstable/fragile.o +SFILE_OBJECTS = hammer/file.o sickle/sic.o common/loud.o +RELEASE_LIBS = cyclone hammer sickle +RELEASE_APPS = cyclist diff --git a/cyclone/Makefile.sources b/cyclone/Makefile.sources new file mode 100644 index 0000000..4d6cc29 --- /dev/null +++ b/cyclone/Makefile.sources @@ -0,0 +1,191 @@ +TYPES = HPLAIN HLOUD HFRAGILE HGROW HFILE HRAND HRANDFILE HRANDGROW \ + HTREE HTREEFILEVEFL HGUI HSEQ \ + SPLAINNOTILDE SPLAIN SSIC SFORKY SFRAGILE SGROW SGROWFORKY \ + SVEFL SARSIC SFILE + +HPLAIN_SOURCES = \ +hammer/testmess.c \ +hammer/accum.c \ +hammer/acos.c \ +hammer/asin.c \ +hammer/Bucket.c \ +hammer/cartopol.c \ +hammer/cosh.c \ +hammer/counter.c \ +hammer/flush.c \ +hammer/forward.c \ +hammer/fromsymbol.c \ +hammer/mean.c \ +hammer/midiflush.c \ +hammer/midiformat.c \ +hammer/midiparse.c \ +hammer/next.c \ +hammer/onebang.c \ +hammer/Peak.c \ +hammer/poltocar.c \ +hammer/sinh.c \ +hammer/split.c \ +hammer/sustain.c \ +hammer/tanh.c \ +hammer/Trough.c \ +hammer/Uzi.c \ +hammer/xbendin.c \ +hammer/xbendin2.c \ +hammer/xbendout.c \ +hammer/xbendout2.c \ +hammer/xnotein.c \ +hammer/xnoteout.c + +HLOUD_SOURCES = \ +hammer/anal.c \ +hammer/bangbang.c \ +hammer/Borax.c \ +hammer/comment.c \ +hammer/cycle.c \ +hammer/decide.c \ +hammer/Decode.c \ +hammer/gate.c \ +hammer/Histo.c \ +hammer/maximum.c \ +hammer/minimum.c \ +hammer/spell.c \ +hammer/spray.c \ +hammer/sprintf.c \ +hammer/switch.c \ +hammer/TogEdge.c + +HFRAGILE_SOURCES = \ +hammer/grab.c \ +hammer/universal.c + +HGROW_SOURCES = \ +hammer/Append.c \ +hammer/bondo.c \ +hammer/buddy.c \ +hammer/Clip.c \ +hammer/funnel.c \ +hammer/iter.c \ +hammer/match.c \ +hammer/past.c \ +hammer/prepend.c \ +hammer/pv.c \ +hammer/speedlim.c \ +hammer/substitute.c \ +hammer/thresh.c \ +hammer/tosymbol.c \ +hammer/zl.c + +HFILE_SOURCES = \ +hammer/capture.c \ +hammer/coll.c + +HRAND_SOURCES = \ +hammer/drunk.c + +HRANDFILE_SOURCES = \ +hammer/prob.c + +HRANDGROW_SOURCES = \ +hammer/urn.c + +HTREE_SOURCES = \ +hammer/offer.c + +HTREEFILEVEFL_SOURCES = \ +hammer/funbuff.c + +HGUI_SOURCES = \ +hammer/active.c \ +hammer/mousefilter.c \ +hammer/MouseState.c + +HSEQ_SOURCES = \ +hammer/seq.c + +SPLAINNOTILDE_SOURCES = \ +sickle/linedrive.c + +SSIC_TILDE = $(TILDE) +SSIC_SOURCES = \ +sickle/abs.c \ +sickle/acos.c \ +sickle/acosh.c \ +sickle/allpass.c \ +sickle/asin.c \ +sickle/asinh.c \ +sickle/atan.c \ +sickle/atan2.c \ +sickle/atanh.c \ +sickle/average.c \ +sickle/avg.c \ +sickle/bitnot.c \ +sickle/bitshift.c \ +sickle/change.c \ +sickle/Clip.c \ +sickle/comb.c \ +sickle/cosh.c \ +sickle/cosx.c \ +sickle/count.c \ +sickle/delay.c \ +sickle/delta.c \ +sickle/deltaclip.c \ +sickle/edge.c \ +sickle/kink.c \ +sickle/log.c \ +sickle/minmax.c \ +sickle/peakamp.c \ +sickle/phasewrap.c \ +sickle/pow.c \ +sickle/rampsmooth.c \ +sickle/rand.c \ +sickle/sah.c \ +sickle/sinh.c \ +sickle/sinx.c \ +sickle/slide.c \ +sickle/Snapshot.c \ +sickle/spike.c \ +sickle/tanh.c \ +sickle/tanx.c \ +sickle/train.c \ +sickle/trapezoid.c \ +sickle/triangle.c \ +sickle/vectral.c + +SFORKY_TILDE = $(TILDE) +SFORKY_SOURCES = \ +sickle/bitand.c \ +sickle/bitor.c \ +sickle/bitxor.c + +SFRAGILE_TILDE = $(TILDE) +SFRAGILE_SOURCES = \ +sickle/cartopol.c \ +sickle/poltocar.c + +SGROW_TILDE = $(TILDE) +SGROW_SOURCES = \ +sickle/click.c \ +sickle/frameaccum.c \ +sickle/framedelta.c \ +sickle/Line.c + +SGROWFORKY_TILDE = $(TILDE) +SGROWFORKY_SOURCES = \ +sickle/Scope.c + +SVEFL_TILDE = $(TILDE) +SVEFL_SOURCES = \ +sickle/cycle.c + +SARSIC_TILDE = $(TILDE) +SARSIC_SOURCES = \ +sickle/index.c \ +sickle/lookup.c \ +sickle/peek.c \ +sickle/play.c \ +sickle/record.c \ +sickle/wave.c + +SFILE_TILDE = $(TILDE) +SFILE_SOURCES = \ +sickle/capture.c diff --git a/cyclone/build_counter b/cyclone/build_counter new file mode 100644 index 0000000..1e05d4b --- /dev/null +++ b/cyclone/build_counter @@ -0,0 +1,3 @@ +#define CYCLONE_VERSION "0.1" +#define CYCLONE_RELEASE "alpha" +#define CYCLONE_BUILD 42 diff --git a/cyclone/cyclone-all.exclude b/cyclone/cyclone-all.exclude new file mode 100644 index 0000000..8b8d91f --- /dev/null +++ b/cyclone/cyclone-all.exclude @@ -0,0 +1,9 @@ +*~ +*.o +*.gz +*.html +*.out +*/*/old +*/*/old/* +*/*/ref +*/*/ref/* diff --git a/cyclone/cyclone-shared.include b/cyclone/cyclone-shared.include new file mode 100644 index 0000000..49cc815 --- /dev/null +++ b/cyclone/cyclone-shared.include @@ -0,0 +1,35 @@ +shared/shared.c +shared/shared.h +shared/unstable/forky.c +shared/unstable/forky.h +shared/unstable/fragile.c +shared/unstable/fragile.h +shared/unstable/pd_imp.h +shared/common/grow.c +shared/common/grow.h +shared/common/loud.c +shared/common/loud.h +shared/common/binport.c +shared/common/binport.h +shared/common/port.c +shared/common/port.h +shared/common/rand.c +shared/common/rand.h +shared/common/vefl.c +shared/common/vefl.h +shared/common/sq.c +shared/common/sq.h +shared/common/bifi.c +shared/common/bifi.h +shared/common/mifi.c +shared/common/mifi.h +shared/hammer/file.c +shared/hammer/file.h +shared/hammer/gui.c +shared/hammer/gui.h +shared/hammer/tree.c +shared/hammer/tree.h +shared/sickle/sic.c +shared/sickle/sic.h +shared/sickle/arsic.c +shared/sickle/arsic.h diff --git a/cyclone/cyclone-test.exclude b/cyclone/cyclone-test.exclude new file mode 100644 index 0000000..ec84f87 --- /dev/null +++ b/cyclone/cyclone-test.exclude @@ -0,0 +1,4 @@ +*~ +import-result.pd +temporary +temporary/* diff --git a/cyclone/cyclone-vicious.exclude b/cyclone/cyclone-vicious.exclude new file mode 100644 index 0000000..5e5a82e --- /dev/null +++ b/cyclone/cyclone-vicious.exclude @@ -0,0 +1,3 @@ +*~ +old +old/* diff --git a/cyclone/hammer/Append.c b/cyclone/hammer/Append.c new file mode 100644 index 0000000..19978c7 --- /dev/null +++ b/cyclone/hammer/Append.c @@ -0,0 +1,207 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/grow.h" + +#define APPEND_INISIZE 32 /* LATER rethink */ +#define APPEND_MAXSIZE 256 + +typedef struct _append +{ + t_object x_ob; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + t_atom *x_message; + t_atom *x_messbuf; + t_atom x_messini[APPEND_INISIZE]; + int x_entered; + int x_auxsize; + t_atom *x_auxbuf; +} t_append; + +static t_class *append_class; + +/* Usually a preallocation method is used, except in special cases of: + 1) reentrant output request, or 2) an output request which would cause + resizing to more than MAXSIZE (no such limit for a 'set' message). + In both special cases, a temporary output buffer is allocated. + A separately preallocated output buffer is not used, thus avoiding + memcpying of the stored message (a small performance gain when the + preallocation method is chosen). Instead, self-invoked 'set' + messages are postponed, using an auxiliary buffer. +*/ + +/* Any Append's output goes through outlet_anything() -> typedmess() */ + +static void append_setnatoms(t_append *x, int natoms) +{ + x->x_message = x->x_messbuf + x->x_size - natoms; + x->x_natoms = natoms; +} + +static void append_anything(t_append *x, t_symbol *s, int ac, t_atom *av) +{ + int reentered = x->x_entered; + int prealloc = !reentered; + int ntotal = x->x_natoms + ac; + t_atom *buf; + x->x_entered = 1; + if (prealloc && ntotal > x->x_size) + { + if (ntotal > APPEND_MAXSIZE) + prealloc = 0; + else + { + int nrequested = ntotal; + x->x_messbuf = grow_withtail(&nrequested, &x->x_natoms, + (char **)&x->x_message, + &x->x_size, x->x_messbuf, + APPEND_INISIZE, x->x_messini, + sizeof(*x->x_message)); + prealloc = (nrequested == ntotal); + } + } + if (prealloc) + { + buf = x->x_message - ac; + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); + } + else + { + /* LATER consider using the stack if ntotal <= MAXSTACK */ + if (buf = getbytes(ntotal * sizeof(*buf))) + { + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + if (x->x_natoms) + memcpy(buf + ac, x->x_message, x->x_natoms * sizeof(*buf)); + outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); + freebytes(buf, ntotal * sizeof(*buf)); + } + } + if (!reentered) + { + x->x_entered = 0; + if (x->x_auxbuf) + { + if (x->x_auxsize <= x->x_size) + { + append_setnatoms(x, x->x_auxsize / 2); + memcpy(x->x_message, x->x_auxbuf + x->x_natoms, + x->x_natoms * sizeof(*x->x_message)); + freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); + } + else + { + if (x->x_messbuf != x->x_messini) + freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); + x->x_size = x->x_auxsize; + x->x_messbuf = x->x_auxbuf; + append_setnatoms(x, x->x_auxsize / 2); + } + x->x_auxbuf = 0; + } + } +} + +static void append_bang(t_append *x) +{ + /* CHECKED: a nop */ +} + +static void append_float(t_append *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + append_anything(x, &s_list, 1, &at); /* CHECKED: converted to list */ +} + +/* CHECKED: incompatible -- LATER consider converting to anything */ +static void append_symbol(t_append *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + append_anything(x, &s_symbol, 1, &at); +} + +/* LATER gpointer */ + +static void append_set(t_append *x, t_symbol *s, int ac, t_atom *av) +{ + int newsize = ac * 2; + if (newsize > 0) + { + if (x->x_entered) + { + if (x->x_auxbuf) + { + loud_warning((t_pd *)x, "\'set\' message overridden"); + freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); + x->x_auxsize = 0; + } + if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf))) + { + memcpy(x->x_auxbuf + ac, av, ac * sizeof(*x->x_auxbuf)); + x->x_auxsize = newsize; + } + } + else + { + t_atom *ap; + if (newsize > x->x_size) + { + int sz = newsize; + x->x_messbuf = grow_nodata(&sz, &x->x_size, x->x_messbuf, + APPEND_INISIZE, x->x_messini, + sizeof(*x->x_messbuf)); + if (sz != newsize) + ac = sz / 2; /* LATER rethink */ + } + append_setnatoms(x, ac); + ap = x->x_message; + while (ac--) *ap++ = *av++; + } + } +} + +static void append_free(t_append *x) +{ + if (x->x_messbuf != x->x_messini) + freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); +} + +static void *append_new(t_symbol *s, int ac, t_atom *av) +{ + t_append *x = (t_append *)pd_new(append_class); + x->x_size = APPEND_INISIZE; + x->x_natoms = 0; + x->x_messbuf = x->x_messini; + x->x_auxbuf = 0; + x->x_entered = 0; + outlet_new((t_object *)x, &s_anything); + append_setnatoms(x, 0); + append_set(x, 0, ac, av); + return (x); +} + +void Append_setup(void) +{ + append_class = class_new(gensym("Append"), + (t_newmethod)append_new, + (t_method)append_free, + sizeof(t_append), 0, + A_GIMME, 0); + class_addbang(append_class, append_bang); + class_addfloat(append_class, append_float); + class_addsymbol(append_class, append_symbol); + class_addlist(append_class, append_anything); /* LATER rethink */ + class_addanything(append_class, append_anything); + class_addmethod(append_class, (t_method)append_set, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/Borax.c b/cyclone/hammer/Borax.c new file mode 100644 index 0000000..26e0ef8 --- /dev/null +++ b/cyclone/hammer/Borax.c @@ -0,0 +1,177 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The first version of this code was written by Olaf Matthes. + It was entirely reimplemented in the hope of adapting it to the + cyclone's guidelines. */ + +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" + +#define BORAX_MAXVOICES 128 /* CHECKME */ + +typedef struct _Borax_voice +{ + int v_index; /* free iff zero */ + double v_onset; + int v_nonsets; +} t_Borax_voice; + +typedef struct _Borax +{ + t_object x_ob; + int x_vel; /* CHECKME t_float controlled with floatinlet + (CHECKME the same in flush) */ + double x_onset; + int x_nonsets; + int x_ndurs; + int x_ndtimes; + int x_minindex; + int x_indices[BORAX_MAXVOICES]; /* 0 (free) or 1 (used) */ + int x_nvoices; + t_Borax_voice x_voices[BORAX_MAXVOICES]; + t_outlet *x_voiceout; + t_outlet *x_nvoicesout; + t_outlet *x_pitchout; + t_outlet *x_velout; + t_outlet *x_ndursout; + t_outlet *x_durout; + t_outlet *x_ndtimesout; + t_outlet *x_dtimeout; +} t_Borax; + +static t_class *Borax_class; + +static void Borax_delta(t_Borax *x) +{ + /* CHECKME first note */ + float dtime = clock_gettimesince(x->x_onset); /* CHECKME */ + outlet_float(x->x_dtimeout, dtime); + outlet_float(x->x_ndtimesout, ++x->x_ndtimes); /* CHECKME */ +} + +static void Borax_durout(t_Borax *x, int pitch) +{ + float dur = clock_gettimesince(x->x_voices[pitch].v_onset); /* CHECKME */ + outlet_float(x->x_durout, dur); + outlet_float(x->x_ndursout, ++x->x_ndurs); /* CHECKME */ +} + +static void Borax_float(t_Borax *x, t_float f) +{ + int pitch; + if (loud_checkint((t_pd *)x, f, &pitch, &s_float)) /* CHECKME */ + { + int index; + if (pitch < 0 || pitch >= BORAX_MAXVOICES) + { + /* CHECKME pitch range, complaints */ + return; + } + index = x->x_voices[pitch].v_index; + if (x->x_vel) + { + if (index) + return; /* CHECKME */ + x->x_indices[index = x->x_minindex] = 1; + while (x->x_indices[++x->x_minindex]); + index++; /* CHECKME one-based? */ + Borax_delta(x); + x->x_onset = clock_getlogicaltime(); /* CHECKME (in delta?) */ + x->x_voices[pitch].v_index = index; + x->x_voices[pitch].v_onset = x->x_onset; + x->x_voices[pitch].v_nonsets = ++x->x_nonsets; + x->x_nvoices++; + } + else + { + if (!index) + return; /* CHECKME */ + index--; + x->x_indices[index] = 0; + if (index < x->x_minindex) x->x_minindex = index; + index++; + Borax_durout(x, pitch); + x->x_voices[pitch].v_index = 0; + x->x_nvoices--; + } + outlet_float(x->x_velout, x->x_vel); + outlet_float(x->x_pitchout, pitch); + outlet_float(x->x_nvoicesout, x->x_nvoices); + outlet_float(x->x_voiceout, index); + outlet_float(((t_object *)x)->ob_outlet, x->x_voices[pitch].v_nonsets); + } +} + +static void Borax_ft1(t_Borax *x, t_floatarg f) +{ + x->x_vel = (int)f; /* CHECKME */ +} + +static void Borax_reset(t_Borax *x) +{ + x->x_vel = 0; + x->x_onset = clock_getlogicaltime(); + x->x_nonsets = x->x_ndurs = x->x_ndtimes = 0; + x->x_minindex = 0; + memset(x->x_indices, 0, sizeof(x->x_indices)); + x->x_nvoices = 0; + memset(x->x_voices, 0, sizeof(x->x_voices)); +} + +static void Borax_bang2(t_Borax *x) +{ + int pitch; + for (pitch = 0; pitch < BORAX_MAXVOICES; pitch++) + { + if (x->x_voices[pitch].v_index) + { + /* CHECKME counters, etc. */ + Borax_durout(x, pitch); + outlet_float(x->x_velout, 0); + outlet_float(x->x_pitchout, pitch); + outlet_float(x->x_nvoicesout, --x->x_nvoices); + outlet_float(x->x_voiceout, x->x_voices[pitch].v_index); + outlet_float(((t_object *)x)->ob_outlet, + x->x_voices[pitch].v_nonsets); + } + } + Borax_reset(x); +} + +/* CHECKME flush in a destructor */ + +static void *Borax_new(void) +{ + t_Borax *x = (t_Borax *)pd_new(Borax_class); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + inlet_new((t_object *)x, (t_pd *)x, &s_bang, gensym("bang2")); + outlet_new((t_object *)x, &s_float); + x->x_voiceout = outlet_new((t_object *)x, &s_float); + x->x_nvoicesout = outlet_new((t_object *)x, &s_float); + x->x_pitchout = outlet_new((t_object *)x, &s_float); + x->x_velout = outlet_new((t_object *)x, &s_float); + x->x_ndursout = outlet_new((t_object *)x, &s_float); + x->x_durout = outlet_new((t_object *)x, &s_float); + x->x_ndtimesout = outlet_new((t_object *)x, &s_float); + x->x_dtimeout = outlet_new((t_object *)x, &s_float); + Borax_reset(x); + return (x); +} + +void Borax_setup(void) +{ + Borax_class = class_new(gensym("Borax"), + (t_newmethod)Borax_new, 0, + sizeof(t_Borax), 0, 0); + class_addfloat(Borax_class, Borax_float); + /* CHECKME list unfolding */ + class_addmethod(Borax_class, (t_method)Borax_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(Borax_class, (t_method)Borax_bang2, + gensym("bang2"), 0); + class_addmethod(Borax_class, (t_method)Borax_delta, + gensym("delta"), 0); +} diff --git a/cyclone/hammer/Bucket.c b/cyclone/hammer/Bucket.c new file mode 100644 index 0000000..036f836 --- /dev/null +++ b/cyclone/hammer/Bucket.c @@ -0,0 +1,137 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a modified version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" + +typedef struct _Bucket +{ + t_object x_ob; + int x_numbucks; + t_float *x_bucks; /* CHECKED: no limit */ + t_outlet **x_outs; + short int x_frozen; /* 0 for thawed, 1 for frozen */ + short int x_dir; /* 0 for L2R, 1 for R2L */ +} t_Bucket; + +static t_class *Bucket_class; + +static void Bucket_bang(t_Bucket *x) +{ + int i = x->x_numbucks; + /* CHECKED: outlets output in right-to-left order */ + while (i--) outlet_float(x->x_outs[i], x->x_bucks[i]); +} + +static void Bucket_float(t_Bucket *x, t_float val) +{ + int i; + + if (!x->x_frozen) + Bucket_bang(x); + if (!x->x_dir) + { + for (i = x->x_numbucks - 1; i > 0; i--) + x->x_bucks[i] = x->x_bucks[i - 1]; + x->x_bucks[0] = val; + } + else + { + for (i = 0; i < x->x_numbucks - 1; i++) + x->x_bucks[i] = x->x_bucks[i + 1]; + x->x_bucks[x->x_numbucks - 1] = val; + } +} + +static void Bucket_freeze(t_Bucket *x) +{ + x->x_frozen = 1; +} + +static void Bucket_thaw(t_Bucket *x) +{ + x->x_frozen = 0; +} + +static void Bucket_roll(t_Bucket *x) +{ + if (x->x_dir) + Bucket_float(x, x->x_bucks[0]); + else + Bucket_float(x, x->x_bucks[x->x_numbucks - 1]); +} + +static void Bucket_rtol(t_Bucket *x) +{ + x->x_dir = 1; +} + +static void Bucket_ltor(t_Bucket *x) +{ + x->x_dir = 0; +} + +static void Bucket_set(t_Bucket *x, t_floatarg f) +{ + int i = x->x_numbucks; + while (i--) x->x_bucks[i] = f; + if (!x->x_frozen) /* CHECKED */ + Bucket_bang(x); +} + +static void Bucket_free(t_Bucket *x) +{ + if (x->x_bucks) + freebytes(x->x_bucks, x->x_numbucks * sizeof(*x->x_bucks)); + if (x->x_outs) + freebytes(x->x_outs, x->x_numbucks * sizeof(*x->x_outs)); +} + +static void *Bucket_new(t_floatarg val) +{ + t_Bucket *x; + int i, nbucks = (int)val; + t_float *bucks; + t_outlet **outs; + if (nbucks < 1) + nbucks = 1; + if (!(bucks = (t_float *)getbytes(nbucks * sizeof(*bucks)))) + return (0); + if (!(outs = (t_outlet **)getbytes(nbucks * sizeof(*outs)))) + { + freebytes(bucks, nbucks * sizeof(*bucks)); + return (0); + } + x = (t_Bucket *)pd_new(Bucket_class); + x->x_numbucks = nbucks; + x->x_bucks = bucks; + x->x_outs = outs; + x->x_frozen = 0; + x->x_dir = 0; + while (nbucks--) *outs++ = outlet_new((t_object *)x, &s_float); + return (x); +} + +void Bucket_setup(void) +{ + Bucket_class = class_new(gensym("Bucket"), + (t_newmethod)Bucket_new, + (t_method)Bucket_free, + sizeof(t_Bucket), 0, A_DEFFLOAT, 0); + class_addbang(Bucket_class, Bucket_bang); + class_addfloat(Bucket_class, Bucket_float); + class_addmethod(Bucket_class, (t_method)Bucket_freeze, gensym("freeze"), 0); + class_addmethod(Bucket_class, (t_method)Bucket_thaw, gensym("thaw"), 0); + class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("L2R"), 0); + class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("R2L"), 0); + /* CHECKED (refman error) roll has no argument */ + class_addmethod(Bucket_class, (t_method)Bucket_roll, gensym("roll"), 0); + /* 3.5 additions */ + class_addmethod(Bucket_class, (t_method)Bucket_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(Bucket_class, (t_method)Bucket_ltor, gensym("l2r"), 0); + class_addmethod(Bucket_class, (t_method)Bucket_rtol, gensym("r2l"), 0); +} diff --git a/cyclone/hammer/Clip.c b/cyclone/hammer/Clip.c new file mode 100644 index 0000000..a06d3a8 --- /dev/null +++ b/cyclone/hammer/Clip.c @@ -0,0 +1,149 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define CLIP_INISIZE 32 /* LATER rethink */ +#define CLIP_MAXSIZE 256 + +typedef struct _clip +{ + t_object x_ob; + float x_f1; + float x_f2; + int x_size; /* as allocated */ + t_atom *x_message; + t_atom x_messini[CLIP_INISIZE]; + int x_entered; +} t_clip; + +static t_class *clip_class; + +/* CHECKED case of f1 > f2: x <= f2 => f1, x > f2 => f2 + (Pd implementation of clip has it the other way around) */ +static void clip_float(t_clip *x, t_float f) +{ + outlet_float(((t_object *)x)->ob_outlet, + (f > x->x_f2 ? x->x_f2 : (f < x->x_f1 ? x->x_f1 : f))); +} + +static void clip_list(t_clip *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + int docopy = 0; + int i; + t_atom *ap; + t_float f1 = x->x_f1; + t_float f2 = x->x_f2; + for (i = 0, ap = av; i < ac; i++, ap++) + { + t_float f; + if (ap->a_type == A_FLOAT) + f = ap->a_w.w_float; + else + { + docopy = 1; + /* CHECKED: symbols inside lists are converted to zeros */ + f = 0; + } + if (f < f1 || f > f2) docopy = 1; + } + if (docopy) + { + t_atom *buf; + t_atom *bp; + int reentered = x->x_entered; + int prealloc = !reentered; + x->x_entered = 1; + if (prealloc && ac > x->x_size) + { + if (ac > CLIP_MAXSIZE) + prealloc = 0; + else + x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, + CLIP_INISIZE, x->x_messini, + sizeof(*x->x_message)); + } + if (prealloc) buf = x->x_message; + else + /* LATER consider using the stack if ntotal <= MAXSTACK */ + buf = getbytes(ac * sizeof(*buf)); + if (buf) + { + for (i = 0, ap = av, bp = buf; i < ac; i++, ap++, bp++) + { + t_float f = (ap->a_type == A_FLOAT ? ap->a_w.w_float : 0); + if (f < f1) + f = f1; + else if (f > f2) + f = f2; + SETFLOAT(bp, f); + } + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, buf); + if (buf != x->x_message) + freebytes(buf, ac * sizeof(*buf)); + } + if (!reentered) + { + x->x_entered = 0; + } + } + else outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + } +} + +static void clip_set(t_clip *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_f1 = 0; + x->x_f2 = 0; + if (ac) /* CHECKED: 'set' without arguments sets both values to 0 */ + { + if (av->a_type == A_FLOAT) /* CHECKED: symbol is converted to 0 */ + x->x_f1 = av->a_w.w_float; + av++; + if (--ac) + { + if (av->a_type == A_FLOAT) + x->x_f2 = av->a_w.w_float; + } + else x->x_f2 = x->x_f1; /* CHECKED */ + } +} + +static void clip_free(t_clip *x) +{ + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); +} + +static void *clip_new(t_symbol *s, int ac, t_atom *av) +{ + t_clip *x = (t_clip *)pd_new(clip_class); + x->x_f1 = 0; + x->x_f2 = 0; + x->x_size = CLIP_INISIZE; + x->x_message = x->x_messini; + x->x_entered = 0; + floatinlet_new((t_object *)x, &x->x_f1); + floatinlet_new((t_object *)x, &x->x_f2); + outlet_new(&x->x_ob, &s_anything); + clip_set(x, 0, ac, av); + return (x); +} + +void Clip_setup(void) +{ + clip_class = class_new(gensym("Clip"), + (t_newmethod)clip_new, + (t_method)clip_free, + sizeof(t_clip), 0, + A_GIMME, 0); + class_addfloat(clip_class, clip_float); + class_addlist(clip_class, clip_list); + class_addmethod(clip_class, (t_method)clip_set, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/Decode.c b/cyclone/hammer/Decode.c new file mode 100644 index 0000000..8317d7e --- /dev/null +++ b/cyclone/hammer/Decode.c @@ -0,0 +1,110 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is an entirely rewritten version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define DECODE_MAXOUTS 8 /* CHECKED (does it make any sense?) */ +#define DECODE_DEFOUTS 1 + +typedef struct _Decode +{ + t_object x_ob; + int x_numouts; + int x_onout; + int x_allon; /* submaster switch */ + int x_alloff; /* master switch */ + t_outlet **x_outs; + t_outlet *x_outbuf[DECODE_MAXOUTS]; +} t_Decode; + +static t_class *Decode_class; + +/* CHECKED: all outlets deliver after any action */ +/* CHECKED: outlets output in right-to-left order */ + +static void Decode_deliver(t_Decode *x) +{ + int i = x->x_numouts; + if (x->x_alloff) + while (i--) outlet_float(x->x_outs[i], 0); + else if (x->x_allon) + while (i--) outlet_float(x->x_outs[i], 1); + else + while (i--) outlet_float(x->x_outs[i], (i == x->x_onout ? 1 : 0)); +} + +static void Decode_float(t_Decode *x, t_floatarg f) +{ + int val = (int)f; + /* CHECKED: out-of-range input is clipped, not ignored */ + if (val < 0) + val = 0; + else if (val >= x->x_numouts) + val = x->x_numouts - 1; + /* CHECKED: while in all-off mode, input is stored, not ignored */ + x->x_onout = val; + Decode_deliver(x); +} + +static void Decode_allon(t_Decode *x, t_floatarg f) +{ + x->x_allon = (f != 0); + Decode_deliver(x); +} + +static void Decode_alloff(t_Decode *x, t_floatarg f) +{ + x->x_alloff = (f != 0); + Decode_deliver(x); +} + +static void Decode_free(t_Decode *x) +{ + if (x->x_outs != x->x_outbuf) + freebytes(x->x_outs, x->x_numouts * sizeof(*x->x_outs)); +} + +static void *Decode_new(t_floatarg val) +{ + t_Decode *x; + int i, nouts = (int)val; + t_outlet **outs; + if (nouts < 1) + nouts = DECODE_DEFOUTS; + if (nouts > DECODE_MAXOUTS) + { + loud_incompatible_max(Decode_class, DECODE_MAXOUTS, "outlets"); + if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) + return (0); + } + else outs = 0; + x = (t_Decode *)pd_new(Decode_class); + x->x_numouts = nouts; + x->x_outs = (outs ? outs : x->x_outbuf); + x->x_onout = 0; + x->x_allon = 0; + x->x_alloff = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); + for (i = 0; i < nouts; i++) + x->x_outs[i] = outlet_new((t_object *)x, &s_float); + return (x); +} + +void Decode_setup(void) +{ + Decode_class = class_new(gensym("Decode"), + (t_newmethod)Decode_new, + (t_method)Decode_free, + sizeof(t_Decode), 0, A_DEFFLOAT, 0); + class_addfloat(Decode_class, Decode_float); + class_addmethod(Decode_class, (t_method)Decode_allon, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(Decode_class, (t_method)Decode_alloff, + gensym("ft2"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/Histo.c b/cyclone/hammer/Histo.c new file mode 100644 index 0000000..efb0deb --- /dev/null +++ b/cyclone/hammer/Histo.c @@ -0,0 +1,103 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is an entirely rewritten version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define HISTO_DEFSIZE 128 + +typedef struct _Histo +{ + t_object x_ob; + int x_size; + unsigned *x_hist; /* LATER consider using 64 bits */ + int x_lastinput; + t_outlet *x_countout; +} t_Histo; + +static t_class *Histo_class; + +static void Histo_clear(t_Histo *x) +{ + int i = x->x_size; + while (i--) x->x_hist[i] = 0; + /* CHECKED: last input is kept */ +} + +static void Histo_doit(t_Histo *x, int val, int doincr) +{ + if (val >= 0 && val < x->x_size) + { + if (doincr) + { + /* CHECKED: only in-range numbers are stored */ + x->x_lastinput = val; + x->x_hist[val]++; + } + outlet_float(x->x_countout, x->x_hist[val]); + /* CHECKED: out-of-range numbers are never passed thru */ + outlet_float(((t_object *)x)->ob_outlet, val); + } +} + +static void Histo_bang(t_Histo *x) +{ + Histo_doit(x, x->x_lastinput, 0); +} + +static void Histo_float(t_Histo *x, t_floatarg f) +{ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */ + Histo_doit(x, i, 1); +} + +static void Histo_ft1(t_Histo *x, t_floatarg f) +{ + /* CHECKED: floats are accepted in second inlet (truncated) */ + Histo_doit(x, (int)f, 0); +} + +static void Histo_free(t_Histo *x) +{ + if (x->x_hist) + freebytes(x->x_hist, x->x_size * sizeof(*x->x_hist)); +} + +static void *Histo_new(t_floatarg f) +{ + t_Histo *x; + int size = (int)f; + unsigned *hist; + if (size < 1) /* CHECKED: 1 is allowed */ + size = HISTO_DEFSIZE; + if (!(hist = (unsigned *)getbytes(size * sizeof(*hist)))) + return (0); + x = (t_Histo *)pd_new(Histo_class); + x->x_size = size; + x->x_hist = hist; + x->x_lastinput = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_countout = outlet_new((t_object *)x, &s_float); + Histo_clear(x); + return (x); +} + +void Histo_setup(void) +{ + Histo_class = class_new(gensym("Histo"), + (t_newmethod)Histo_new, + (t_method)Histo_free, + sizeof(t_Histo), 0, A_DEFFLOAT, 0); + class_addbang(Histo_class, Histo_bang); + class_addfloat(Histo_class, Histo_float); + class_addmethod(Histo_class, (t_method)Histo_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(Histo_class, (t_method)Histo_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/Makefile b/cyclone/hammer/Makefile new file mode 100644 index 0000000..54383c3 --- /dev/null +++ b/cyclone/hammer/Makefile @@ -0,0 +1,3 @@ +ROOT_DIR = ../.. +redefault: allhammers.c default +include $(ROOT_DIR)/Makefile.common diff --git a/cyclone/hammer/Makefile.objects b/cyclone/hammer/Makefile.objects new file mode 100644 index 0000000..0ac0a87 --- /dev/null +++ b/cyclone/hammer/Makefile.objects @@ -0,0 +1,14 @@ +SHARED_OBJECTS = \ +unstable/fragile.o \ +common/loud.o \ +common/grow.o \ +common/rand.o \ +common/vefl.o \ +common/sq.o \ +common/bifi.o \ +common/mifi.o \ +common/binport.o \ +common/port.o \ +hammer/file.o \ +hammer/gui.o \ +hammer/tree.o diff --git a/cyclone/hammer/Makefile.sources b/cyclone/hammer/Makefile.sources new file mode 100644 index 0000000..5df97f5 --- /dev/null +++ b/cyclone/hammer/Makefile.sources @@ -0,0 +1,80 @@ +CX_SOURCES = \ +hammer.c + +OTHER_SOURCES = \ +allhammers.c \ +testmess.c \ +accum.c \ +acos.c \ +active.c \ +anal.c \ +Append.c \ +asin.c \ +bangbang.c \ +bondo.c \ +Borax.c \ +Bucket.c \ +buddy.c \ +capture.c \ +cartopol.c \ +Clip.c \ +coll.c \ +comment.c \ +cosh.c \ +counter.c \ +cycle.c \ +decide.c \ +Decode.c \ +drunk.c \ +flush.c \ +forward.c \ +fromsymbol.c \ +funbuff.c \ +funnel.c \ +gate.c \ +grab.c \ +Histo.c \ +iter.c \ +match.c \ +maximum.c \ +mean.c \ +midiflush.c \ +midiformat.c \ +midiparse.c \ +minimum.c \ +mousefilter.c \ +MouseState.c \ +next.c \ +offer.c \ +onebang.c \ +past.c \ +Peak.c \ +poltocar.c \ +prepend.c \ +prob.c \ +pv.c \ +seq.c \ +sinh.c \ +speedlim.c \ +spell.c \ +split.c \ +spray.c \ +sprintf.c \ +substitute.c \ +sustain.c \ +switch.c \ +tanh.c \ +thresh.c \ +TogEdge.c \ +tosymbol.c \ +Trough.c \ +universal.c \ +urn.c \ +Uzi.c \ +xbendin.c \ +xbendin2.c \ +xbendout.c \ +xbendout2.c \ +xnotein.c \ +xnoteout.c \ +zl.c diff --git a/cyclone/hammer/MouseState.c b/cyclone/hammer/MouseState.c new file mode 100644 index 0000000..3b831bf --- /dev/null +++ b/cyclone/hammer/MouseState.c @@ -0,0 +1,153 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "hammer/gui.h" + +typedef struct _MouseState +{ + t_object x_ob; + int x_ispolling; + int x_wasbanged; + int x_waszeroed; + int x_hlast; + int x_vlast; + int x_hzero; + int x_vzero; + t_outlet *x_hposout; + t_outlet *x_vposout; + t_outlet *x_hdiffout; + t_outlet *x_vdiffout; +} t_MouseState; + +static t_class *MouseState_class; + +static void MouseState_anything(t_MouseState *x, + t_symbol *s, int ac, t_atom *av) +{ + /* dummy method, filtering out those messages from gui, + which are not handled explicitly */ +} + +static void MouseState_doup(t_MouseState *x, t_floatarg f) +{ + outlet_float(((t_object *)x)->ob_outlet, ((int)f ? 0 : 1)); +} + +static void MouseState_dobang(t_MouseState *x, t_floatarg f1, t_floatarg f2) +{ + if (x->x_wasbanged) + { + int h = (int)f1, v = (int)f2; + outlet_float(x->x_vdiffout, v - x->x_vlast); + outlet_float(x->x_hdiffout, h - x->x_hlast); + outlet_float(x->x_vposout, v - x->x_vzero); + outlet_float(x->x_hposout, h - x->x_hzero); + x->x_hlast = h; + x->x_vlast = v; + x->x_wasbanged = 0; + } +} + +static void MouseState_dozero(t_MouseState *x, t_floatarg f1, t_floatarg f2) +{ + if (x->x_waszeroed) + { + int h = (int)f1, v = (int)f2; + x->x_hzero = h; + x->x_vzero = v; + x->x_waszeroed = 0; + } +} + +static void MouseState_dopoll(t_MouseState *x, t_floatarg f1, t_floatarg f2) +{ + if (x->x_ispolling) + { + x->x_wasbanged = 1; + MouseState_dobang(x, f1, f2); + } +} + +static void MouseState_bang(t_MouseState *x) +{ + hammergui_mousexy(gensym("_bang")); + x->x_wasbanged = 1; +} + +static void MouseState_poll(t_MouseState *x) +{ + if (!x->x_ispolling) + { + x->x_ispolling = 1; + hammergui_startpolling((t_pd *)x); + } +} + +static void MouseState_nopoll(t_MouseState *x) +{ + if (x->x_ispolling) + { + x->x_ispolling = 0; + hammergui_stoppolling((t_pd *)x); + } +} + +static void MouseState_zero(t_MouseState *x) +{ + hammergui_mousexy(gensym("_zero")); + x->x_waszeroed = 1; +} + +static void MouseState_reset(t_MouseState *x) +{ + x->x_hzero = x->x_vzero = 0; +} + +static void MouseState_free(t_MouseState *x) +{ + MouseState_nopoll(x); + hammergui_unbindmouse((t_pd *)x); +} + +static void *MouseState_new(void) +{ + t_MouseState *x = (t_MouseState *)pd_new(MouseState_class); + x->x_ispolling = x->x_wasbanged = x->x_waszeroed = 0; + outlet_new((t_object *)x, &s_float); + x->x_hposout = outlet_new((t_object *)x, &s_float); + x->x_vposout = outlet_new((t_object *)x, &s_float); + x->x_hdiffout = outlet_new((t_object *)x, &s_float); + x->x_vdiffout = outlet_new((t_object *)x, &s_float); + hammergui_bindmouse((t_pd *)x); + hammergui_willpoll(); + MouseState_reset(x); + return (x); +} + +void MouseState_setup(void) +{ + MouseState_class = class_new(gensym("MouseState"), + (t_newmethod)MouseState_new, + (t_method)MouseState_free, + sizeof(t_MouseState), 0, 0); + class_addanything(MouseState_class, MouseState_anything); + class_addmethod(MouseState_class, (t_method)MouseState_doup, + gensym("_up"), A_FLOAT, 0); + class_addmethod(MouseState_class, (t_method)MouseState_dobang, + gensym("_bang"), A_FLOAT, A_FLOAT, 0); + class_addmethod(MouseState_class, (t_method)MouseState_dozero, + gensym("_zero"), A_FLOAT, A_FLOAT, 0); + class_addmethod(MouseState_class, (t_method)MouseState_dopoll, + gensym("_poll"), A_FLOAT, A_FLOAT, 0); + class_addbang(MouseState_class, MouseState_bang); + class_addmethod(MouseState_class, (t_method)MouseState_poll, + gensym("poll"), 0); + class_addmethod(MouseState_class, (t_method)MouseState_nopoll, + gensym("nopoll"), 0); + class_addmethod(MouseState_class, (t_method)MouseState_zero, + gensym("zero"), 0); + class_addmethod(MouseState_class, (t_method)MouseState_reset, + gensym("reset"), 0); +} diff --git a/cyclone/hammer/Peak.c b/cyclone/hammer/Peak.c new file mode 100644 index 0000000..6f7e30c --- /dev/null +++ b/cyclone/hammer/Peak.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +#define PEAK_INITIAL 0 + +typedef struct _Peak +{ + t_object x_ob; + t_float x_value; + t_outlet *x_out2; + t_outlet *x_out3; +} t_Peak; + +static t_class *Peak_class; + +static void Peak_bang(t_Peak *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void Peak_ft1(t_Peak *x, t_floatarg f) +{ + /* CHECKME loud_checkint */ + outlet_float(x->x_out3, 0); /* CHECKME */ + outlet_float(x->x_out2, 1); + outlet_float(((t_object *)x)->ob_outlet, x->x_value = f); +} + +static void Peak_float(t_Peak *x, t_float f) +{ + /* CHECKME loud_checkint */ + if (f > x->x_value) Peak_ft1(x, f); + else + { + outlet_float(x->x_out3, 1); + outlet_float(x->x_out2, 0); + } +} + +static void *Peak_new(t_floatarg f) +{ + t_Peak *x = (t_Peak *)pd_new(Peak_class); + x->x_value = PEAK_INITIAL; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_float); + x->x_out3 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void Peak_setup(void) +{ + Peak_class = class_new(gensym("Peak"), + (t_newmethod)Peak_new, 0, + sizeof(t_Peak), 0, 0); + class_addbang(Peak_class, Peak_bang); + class_addfloat(Peak_class, Peak_float); + class_addmethod(Peak_class, (t_method)Peak_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/TogEdge.c b/cyclone/hammer/TogEdge.c new file mode 100644 index 0000000..79c26ec --- /dev/null +++ b/cyclone/hammer/TogEdge.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +typedef struct _TogEdge +{ + t_object x_ob; + int x_wason; + t_outlet *x_out1; +} t_TogEdge; + +static t_class *TogEdge_class; + +static void TogEdge_bang(t_TogEdge *x) +{ + if (x->x_wason) + { + x->x_wason = 0; + outlet_bang(x->x_out1); + } + else + { + x->x_wason = 1; + outlet_bang(((t_object *)x)->ob_outlet); + } +} + +static void TogEdge_float(t_TogEdge *x, t_float f) +{ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */ + { + if (x->x_wason) + { + if (!i) + { + x->x_wason = 0; + outlet_bang(x->x_out1); + } + } + else + { + if (i) + { + x->x_wason = 1; + outlet_bang(((t_object *)x)->ob_outlet); + } + } + } +} + +static void *TogEdge_new(void) +{ + t_TogEdge *x = (t_TogEdge *)pd_new(TogEdge_class); + x->x_wason = 0; /* CHECKED */ + outlet_new((t_object *)x, &s_bang); + x->x_out1 = outlet_new((t_object *)x, &s_bang); + return (x); +} + +void TogEdge_setup(void) +{ + TogEdge_class = class_new(gensym("TogEdge"), + (t_newmethod)TogEdge_new, 0, + sizeof(t_TogEdge), 0, 0); + class_addbang(TogEdge_class, TogEdge_bang); + class_addfloat(TogEdge_class, TogEdge_float); +} diff --git a/cyclone/hammer/Trough.c b/cyclone/hammer/Trough.c new file mode 100644 index 0000000..27b19ba --- /dev/null +++ b/cyclone/hammer/Trough.c @@ -0,0 +1,63 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +#define TROUGH_INITIAL 128 /* CHECKME */ + +typedef struct _Trough +{ + t_object x_ob; + t_float x_value; + t_outlet *x_out2; + t_outlet *x_out3; +} t_Trough; + +static t_class *Trough_class; + +static void Trough_bang(t_Trough *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void Trough_ft1(t_Trough *x, t_floatarg f) +{ + /* CHECKME loud_checkint */ + outlet_float(x->x_out3, 0); /* CHECKME */ + outlet_float(x->x_out2, 1); + outlet_float(((t_object *)x)->ob_outlet, x->x_value = f); +} + +static void Trough_float(t_Trough *x, t_float f) +{ + /* CHECKME loud_checkint */ + if (f < x->x_value) Trough_ft1(x, f); + else + { + outlet_float(x->x_out3, 1); + outlet_float(x->x_out2, 0); + } +} + +static void *Trough_new(t_floatarg f) +{ + t_Trough *x = (t_Trough *)pd_new(Trough_class); + x->x_value = TROUGH_INITIAL; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_float); + x->x_out3 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void Trough_setup(void) +{ + Trough_class = class_new(gensym("Trough"), + (t_newmethod)Trough_new, 0, + sizeof(t_Trough), 0, 0); + class_addbang(Trough_class, Trough_bang); + class_addfloat(Trough_class, Trough_float); + class_addmethod(Trough_class, (t_method)Trough_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/Uzi.c b/cyclone/hammer/Uzi.c new file mode 100644 index 0000000..c773c6b --- /dev/null +++ b/cyclone/hammer/Uzi.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKME negative 'nbangs' value set during run-time */ + +#include "m_pd.h" + +typedef struct _Uzi +{ + t_object x_obj; + t_float x_nbangs; + int x_count; + int x_running; + t_outlet *x_out2; + t_outlet *x_out3; +} t_Uzi; + +static t_class *Uzi_class; + +#define UZI_RUNNING 1 +#define UZI_PAUSED 2 + +static void Uzi_dobang(t_Uzi *x) +{ + /* CHECKME reentrancy */ + if (!x->x_running) + { + int count, nbangs = (int)x->x_nbangs; + x->x_running = UZI_RUNNING; + for (count = x->x_count + 1; count <= nbangs; count++) + { + outlet_float(x->x_out3, count); + outlet_bang(((t_object *)x)->ob_outlet); + if (x->x_running == UZI_PAUSED) + { + /* CHECKED: carry bang not sent, even if this is last bang */ + x->x_count = count; + return; + } + } + /* CHECKED: carry bang sent also when there are no left-outlet bangs */ + /* CHECKED: sent after left outlet, not before */ + outlet_bang(x->x_out2); + x->x_count = 0; + x->x_running = 0; + } +} + +static void Uzi_bang(t_Uzi *x) +{ + /* CHECKED: always restarts (when paused too) */ + x->x_count = 0; + x->x_running = 0; + Uzi_dobang(x); +} + +static void Uzi_float(t_Uzi *x, t_float f) +{ + /* CHECKED: always sets a new value and restarts (when paused too) */ + x->x_nbangs = f; + Uzi_bang(x); +} + +/* CHECKED: 'pause, resume' (but not just 'resume') + sends a carry bang when not running (a bug?) */ +static void Uzi_pause(t_Uzi *x) +{ + if (!x->x_running) + x->x_count = (int)x->x_nbangs; /* bug emulation? */ + x->x_running = UZI_PAUSED; +} + +static void Uzi_resume(t_Uzi *x) +{ + if (x->x_running == UZI_PAUSED) + { + x->x_running = 0; + Uzi_dobang(x); + } +} + +static void *Uzi_new(t_floatarg f) +{ + t_Uzi *x = (t_Uzi *)pd_new(Uzi_class); + x->x_nbangs = (f > 1. ? f : 1.); + x->x_count = 0; + x->x_running = 0; + /* CHECKED: set when paused, but then 'resume' is blocked (a bug?) */ + floatinlet_new((t_object *)x, &x->x_nbangs); + outlet_new((t_object *)x, &s_bang); + x->x_out2 = outlet_new((t_object *)x, &s_bang); + x->x_out3 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void Uzi_setup(void) +{ + Uzi_class = class_new(gensym("Uzi"), + (t_newmethod)Uzi_new, 0, + sizeof(t_Uzi), 0, A_DEFFLOAT, 0); + class_addbang(Uzi_class, Uzi_bang); + class_addfloat(Uzi_class, Uzi_float); + class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("pause"), 0); + class_addmethod(Uzi_class, (t_method)Uzi_pause, gensym("break"), 0); + class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("resume"), 0); + class_addmethod(Uzi_class, (t_method)Uzi_resume, gensym("continue"), 0); +} diff --git a/cyclone/hammer/accum.c b/cyclone/hammer/accum.c new file mode 100644 index 0000000..d266fb3 --- /dev/null +++ b/cyclone/hammer/accum.c @@ -0,0 +1,68 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a slightly edited version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" + +typedef struct _accum +{ + t_object x_ob; + t_float x_total; +} t_accum; + +static t_class *accum_class; + +static void accum_set(t_accum *x, t_floatarg val) +{ + x->x_total = val; +} + +static void accum_bang(t_accum *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_total); +} + +static void accum_float(t_accum *x, t_floatarg val) +{ + /* LATER reconsider int/float dilemma */ + accum_set(x, val); + accum_bang(x); +} + +static void accum_add(t_accum *x, t_floatarg val) +{ + /* LATER reconsider int/float dilemma */ + x->x_total += val; +} + +static void accum_mult(t_accum *x, t_floatarg val) +{ + x->x_total *= val; +} + +static void *accum_new(t_floatarg val) +{ + t_accum *x = (t_accum *)pd_new(accum_class); + x->x_total = val; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void accum_setup(void) +{ + accum_class = class_new(gensym("accum"), (t_newmethod)accum_new, 0, + sizeof(t_accum), 0, A_DEFFLOAT, 0); + class_addbang(accum_class, accum_bang); + class_addfloat(accum_class, accum_float); + class_addmethod(accum_class, (t_method)accum_add, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(accum_class, (t_method)accum_mult, + gensym("ft2"), A_FLOAT, 0); + class_addmethod(accum_class, (t_method)accum_set, + gensym("set"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/acos.c b/cyclone/hammer/acos.c new file mode 100644 index 0000000..3f3abea --- /dev/null +++ b/cyclone/hammer/acos.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define acosf acos +#endif + +typedef struct _acos +{ + t_object x_ob; + float x_value; +} t_acos; + +static t_class *acos_class; + +static void acos_bang(t_acos *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void acos_float(t_acos *x, t_float f) +{ + if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ + outlet_float(((t_object *)x)->ob_outlet, x->x_value = acosf(f)); +} + +static void *acos_new(t_floatarg f) +{ + t_acos *x = (t_acos *)pd_new(acos_class); + if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ + x->x_value = acosf(f); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void acos_setup(void) +{ + acos_class = class_new(gensym("acos"), + (t_newmethod)acos_new, 0, + sizeof(t_acos), 0, A_DEFFLOAT, 0); + class_addbang(acos_class, acos_bang); + class_addfloat(acos_class, acos_float); +} diff --git a/cyclone/hammer/active.c b/cyclone/hammer/active.c new file mode 100644 index 0000000..9d10f80 --- /dev/null +++ b/cyclone/hammer/active.c @@ -0,0 +1,55 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "hammer/gui.h" + +typedef struct _active +{ + t_object x_ob; + t_symbol *x_cvname; + int x_on; +} t_active; + +static t_class *active_class; + +static void active_dofocus(t_active *x, t_symbol *s, t_floatarg f) +{ + if ((int)f) + { + int on = (s == x->x_cvname); + if (on != x->x_on) + outlet_float(((t_object *)x)->ob_outlet, x->x_on = on); + } + else if (x->x_on && s == x->x_cvname) + outlet_float(((t_object *)x)->ob_outlet, x->x_on = 0); +} + +static void active_free(t_active *x) +{ + hammergui_unbindfocus((t_pd *)x); +} + +static void *active_new(void) +{ + t_active *x = (t_active *)pd_new(active_class); + char buf[32]; + sprintf(buf, ".x%x.c", (int)canvas_getcurrent()); + x->x_cvname = gensym(buf); + x->x_on = 0; + outlet_new((t_object *)x, &s_float); + hammergui_bindfocus((t_pd *)x); + return (x); +} + +void active_setup(void) +{ + active_class = class_new(gensym("active"), + (t_newmethod)active_new, + (t_method)active_free, + sizeof(t_active), CLASS_NOINLET, 0); + class_addmethod(active_class, (t_method)active_dofocus, + gensym("_focus"), A_SYMBOL, A_FLOAT, 0); +} diff --git a/cyclone/hammer/allhammers.c b/cyclone/hammer/allhammers.c new file mode 100644 index 0000000..e6d8235 --- /dev/null +++ b/cyclone/hammer/allhammers.c @@ -0,0 +1,160 @@ +// Do not edit this file, run "make" instead. + +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +void accum_setup(void); +void acos_setup(void); +void active_setup(void); +void anal_setup(void); +void Append_setup(void); +void asin_setup(void); +void bangbang_setup(void); +void bondo_setup(void); +void Borax_setup(void); +void Bucket_setup(void); +void buddy_setup(void); +void capture_setup(void); +void cartopol_setup(void); +void Clip_setup(void); +void coll_setup(void); +void comment_setup(void); +void cosh_setup(void); +void counter_setup(void); +void cycle_setup(void); +void decide_setup(void); +void Decode_setup(void); +void drunk_setup(void); +void flush_setup(void); +void forward_setup(void); +void fromsymbol_setup(void); +void funbuff_setup(void); +void funnel_setup(void); +void gate_setup(void); +void grab_setup(void); +void Histo_setup(void); +void iter_setup(void); +void match_setup(void); +void maximum_setup(void); +void mean_setup(void); +void midiflush_setup(void); +void midiformat_setup(void); +void midiparse_setup(void); +void minimum_setup(void); +void mousefilter_setup(void); +void MouseState_setup(void); +void next_setup(void); +void offer_setup(void); +void onebang_setup(void); +void past_setup(void); +void Peak_setup(void); +void poltocar_setup(void); +void prepend_setup(void); +void prob_setup(void); +void pv_setup(void); +void seq_setup(void); +void sinh_setup(void); +void speedlim_setup(void); +void spell_setup(void); +void split_setup(void); +void spray_setup(void); +void sprintf_setup(void); +void substitute_setup(void); +void sustain_setup(void); +void switch_setup(void); +void tanh_setup(void); +void testmess_setup(void); +void thresh_setup(void); +void TogEdge_setup(void); +void tosymbol_setup(void); +void Trough_setup(void); +void universal_setup(void); +void urn_setup(void); +void Uzi_setup(void); +void xbendin2_setup(void); +void xbendin_setup(void); +void xbendout2_setup(void); +void xbendout_setup(void); +void xnotein_setup(void); +void xnoteout_setup(void); +void zl_setup(void); + +void allhammers_setup(void) +{ + accum_setup(); + acos_setup(); + active_setup(); + anal_setup(); + Append_setup(); + asin_setup(); + bangbang_setup(); + bondo_setup(); + Borax_setup(); + Bucket_setup(); + buddy_setup(); + capture_setup(); + cartopol_setup(); + Clip_setup(); + coll_setup(); + comment_setup(); + cosh_setup(); + counter_setup(); + cycle_setup(); + decide_setup(); + Decode_setup(); + drunk_setup(); + flush_setup(); + forward_setup(); + fromsymbol_setup(); + funbuff_setup(); + funnel_setup(); + gate_setup(); + grab_setup(); + Histo_setup(); + iter_setup(); + match_setup(); + maximum_setup(); + mean_setup(); + midiflush_setup(); + midiformat_setup(); + midiparse_setup(); + minimum_setup(); + mousefilter_setup(); + MouseState_setup(); + next_setup(); + offer_setup(); + onebang_setup(); + past_setup(); + Peak_setup(); + poltocar_setup(); + prepend_setup(); + prob_setup(); + pv_setup(); + seq_setup(); + sinh_setup(); + speedlim_setup(); + spell_setup(); + split_setup(); + spray_setup(); + sprintf_setup(); + substitute_setup(); + sustain_setup(); + switch_setup(); + tanh_setup(); + testmess_setup(); + thresh_setup(); + TogEdge_setup(); + tosymbol_setup(); + Trough_setup(); + universal_setup(); + urn_setup(); + Uzi_setup(); + xbendin2_setup(); + xbendin_setup(); + xbendout2_setup(); + xbendout_setup(); + xnotein_setup(); + xnoteout_setup(); + zl_setup(); +} diff --git a/cyclone/hammer/anal.c b/cyclone/hammer/anal.c new file mode 100644 index 0000000..477eb20 --- /dev/null +++ b/cyclone/hammer/anal.c @@ -0,0 +1,108 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" + +#define ANAL_DEFSIZE 128 +#define ANAL_MAXSIZE 1024 + +typedef struct _anal +{ + t_object x_ob; + int x_value; /* negative, if initialized or reset */ + int x_size; + int x_bytesize; + int *x_table; + /* CHECKED: the 'weight' count is a signed short (2 bytes), + wrapping into negative domain without any warning. + LATER consider complaining at == SHRT_MAX. */ +} t_anal; + +static t_class *anal_class; + +static void anal_reset(t_anal *x) +{ + x->x_value = -1; +} + +static void anal_clear(t_anal *x) +{ + memset(x->x_table, 0, x->x_bytesize); +} + +static void anal_float(t_anal *x, t_float f) +{ + int value; + if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */ + { + /* CHECKED: any input negative or >= size is ignored with an error + -- there is no output, and a previous state is kept. */ + if (value >= 0 && value < x->x_size) + { + if (x->x_value >= 0) + { + t_atom at[3]; + int ndx = x->x_value * x->x_size + value; + x->x_table[ndx]++; + SETFLOAT(at, x->x_value); + SETFLOAT(&at[1], value); + SETFLOAT(&at[2], x->x_table[ndx]); + outlet_list(((t_object *)x)->ob_outlet, &s_list, 3, at); + } + x->x_value = value; + } + else loud_error((t_pd *)x, "%d outside of table bounds", value); + } +} + +static void anal_free(t_anal *x) +{ + if (x->x_table) + freebytes(x->x_table, x->x_bytesize); +} + +static void *anal_new(t_floatarg f) +{ + t_anal *x; + int size = (int)f; + int bytesize; + int *table; + if (size < 1) + /* CHECKED: 1 is allowed (such an object rejects any nonzero input) */ + size = ANAL_DEFSIZE; + else if (size > ANAL_MAXSIZE) + { + /* CHECKED: */ + loud_warning(&anal_class, "size too large, using %d", ANAL_MAXSIZE); + size = ANAL_MAXSIZE; /* LATER switch into a 'sparse' mode */ + } + /* CHECKED: actually the bytesize is size * size * sizeof(short), + and it shows up in */ + bytesize = size * size * sizeof(*table); + if (!(table = (int *)getbytes(bytesize))) + return (0); + x = (t_anal *)pd_new(anal_class); + x->x_size = size; + x->x_bytesize = bytesize; + x->x_table = table; + outlet_new((t_object *)x, &s_list); + anal_reset(x); + anal_clear(x); + return (x); +} + +void anal_setup(void) +{ + anal_class = class_new(gensym("anal"), + (t_newmethod)anal_new, + (t_method)anal_free, + sizeof(t_anal), 0, A_DEFFLOAT, 0); + class_addfloat(anal_class, anal_float); + class_addmethod(anal_class, (t_method)anal_reset, + gensym("reset"), 0); + class_addmethod(anal_class, (t_method)anal_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/asin.c b/cyclone/hammer/asin.c new file mode 100644 index 0000000..0aa8db7 --- /dev/null +++ b/cyclone/hammer/asin.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define asinf asin +#endif + +typedef struct _asin +{ + t_object x_ob; + float x_value; +} t_asin; + +static t_class *asin_class; + +static void asin_bang(t_asin *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void asin_float(t_asin *x, t_float f) +{ + if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ + outlet_float(((t_object *)x)->ob_outlet, x->x_value = asinf(f)); +} + +static void *asin_new(t_floatarg f) +{ + t_asin *x = (t_asin *)pd_new(asin_class); + if (f < -1.0) f = -1.0; else if (f > 1.0) f = 1.0; /* CHECKME */ + x->x_value = asinf(f); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void asin_setup(void) +{ + asin_class = class_new(gensym("asin"), + (t_newmethod)asin_new, 0, + sizeof(t_asin), 0, A_DEFFLOAT, 0); + class_addbang(asin_class, asin_bang); + class_addfloat(asin_class, asin_float); +} diff --git a/cyclone/hammer/bangbang.c b/cyclone/hammer/bangbang.c new file mode 100644 index 0000000..bebd26e --- /dev/null +++ b/cyclone/hammer/bangbang.c @@ -0,0 +1,73 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a modified version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define BANGBANG_MINOUTS 1 +#define BANGBANG_MAXOUTS 40 /* CHECKED (just clipped without warning) */ +#define BANGBANG_DEFOUTS 2 + +typedef struct _bangbang +{ + t_object x_ob; + int x_nouts; + t_outlet **x_outs; + t_outlet *x_outbuf[BANGBANG_DEFOUTS]; +} t_bangbang; + +static t_class *bangbang_class; + +static void bangbang_bang(t_bangbang *x) +{ + int i = x->x_nouts; + while (i--) outlet_bang(x->x_outs[i]); +} + +static void bangbang_anything(t_bangbang *x, t_symbol *s, int ac, t_atom *av) +{ + bangbang_bang(x); +} + +static void bangbang_free(t_bangbang *x) +{ + if (x->x_outs != x->x_outbuf) + freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); +} + +static void *bangbang_new(t_floatarg val) +{ + t_bangbang *x; + int i, nouts = (int)val; + t_outlet **outs; + if (nouts < BANGBANG_MINOUTS) + nouts = BANGBANG_DEFOUTS; + if (nouts > BANGBANG_MAXOUTS) + loud_incompatible_max(bangbang_class, BANGBANG_MAXOUTS, "outlets"); + if (nouts > BANGBANG_DEFOUTS) + { + if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) + return (0); + } + else outs = 0; + x = (t_bangbang *)pd_new(bangbang_class); + x->x_nouts = nouts; + x->x_outs = (outs ? outs : x->x_outbuf); + for (i = 0; i < nouts; i++) + x->x_outs[i] = outlet_new((t_object *)x, &s_bang); + return (x); +} + +void bangbang_setup(void) +{ + bangbang_class = class_new(gensym("bangbang"), + (t_newmethod)bangbang_new, + (t_method)bangbang_free, + sizeof(t_bangbang), 0, A_DEFFLOAT, 0); + class_addbang(bangbang_class, bangbang_bang); + class_addanything(bangbang_class, bangbang_anything); +} diff --git a/cyclone/hammer/bondo.c b/cyclone/hammer/bondo.c new file mode 100644 index 0000000..2fcdce3 --- /dev/null +++ b/cyclone/hammer/bondo.c @@ -0,0 +1,394 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER revisit buffer handling (maxsize, reentrancy) */ +/* LATER rethink handling of symbols */ + +/* CHECKED: if 'n' argument is given, then store whole messages, instead of + distributing atoms across successive slots. This is a new, buddy-like + behaviour. */ +/* CHECKED: without 'n' argument, 'symbol test' is parsed as two symbol atoms, + but 'float 1' (or 'list 1') as a single float. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define BONDO_MINSLOTS 2 +#define BONDO_INISIZE 4 /* LATER rethink (useful only in multiatom mode) */ + +typedef struct _bondo +{ + t_object x_ob; + t_float x_delay; + int x_multiatom; + int x_nslots; + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; + t_outlet **x_outs; + t_clock *x_clock; +} t_bondo; + +typedef struct _bondo_proxy +{ + t_object p_ob; + t_bondo *p_master; + int p_id; + t_symbol *p_selector; + t_float p_float; + t_symbol *p_symbol; + t_gpointer *p_pointer; + int p_size; /* as allocated */ + int p_natoms; /* as used */ + t_atom *p_message; + t_atom p_messini[BONDO_INISIZE]; +} t_bondo_proxy; + +static t_class *bondo_class; +static t_class *bondo_proxy_class; + +static void bondo_doit(t_bondo *x) +{ + t_bondo_proxy **p = (t_bondo_proxy **)x->x_proxies; + int i = x->x_nslots; + p = (t_bondo_proxy **)x->x_proxies; + i = x->x_nslots; + while (i--) + { + t_symbol *s = p[i]->p_selector; + /* LATER consider complaining about extra arguments (CHECKED) */ + if (s == &s_bang) + outlet_bang(x->x_outs[i]); + else if (s == &s_float) + outlet_float(x->x_outs[i], p[i]->p_float); + else if (s == &s_symbol && p[i]->p_symbol) + { + /* LATER rethink */ + if (x->x_multiatom) + outlet_symbol(x->x_outs[i], p[i]->p_symbol); + else + outlet_anything(x->x_outs[i], p[i]->p_symbol, 0, 0); + } + else if (s == &s_pointer) + { + /* LATER */ + } + else if (s == &s_list) + outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + else if (s) /* CHECKED: a slot may be inactive (in multiatom mode) */ + outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + } +} + +static void bondo_arm(t_bondo *x) +{ + if (x->x_delay <= 0) bondo_doit(x); + else clock_delay(x->x_clock, x->x_delay); +} + +static void bondo_proxy_bang(t_bondo_proxy *x) +{ + bondo_arm(x->p_master); /* CHECKED: bang in any inlet works in this way */ +} + +static void bondo_proxy_dofloat(t_bondo_proxy *x, t_float f, int doit) +{ + x->p_selector = &s_float; + x->p_float = f; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_float(t_bondo_proxy *x, t_float f) +{ + bondo_proxy_dofloat(x, f, 1); +} + +static void bondo_proxy_dosymbol(t_bondo_proxy *x, t_symbol *s, int doit) +{ + x->p_selector = &s_symbol; + x->p_symbol = s; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_symbol(t_bondo_proxy *x, t_symbol *s) +{ + bondo_proxy_dosymbol(x, s, 1); +} + +static void bondo_proxy_dopointer(t_bondo_proxy *x, t_gpointer *gp, int doit) +{ + x->p_selector = &s_pointer; + x->p_pointer = gp; + x->p_natoms = 0; /* defensive */ + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_pointer(t_bondo_proxy *x, t_gpointer *gp) +{ + bondo_proxy_dopointer(x, gp, 1); +} + +/* CHECKED: the slots fire in right-to-left order, + but they trigger only once (refman error) */ +static void bondo_distribute(t_bondo *x, int startid, + t_symbol *s, int ac, t_atom *av, int doit) +{ + t_atom *ap = av; + t_bondo_proxy **pp; + int id = startid + ac; + if (s) id++; + if (id > x->x_nslots) + id = x->x_nslots; + ap += id - startid; + pp = (t_bondo_proxy **)(x->x_proxies + id); + if (s) ap--; + while (ap-- > av) + { + pp--; + if (ap->a_type == A_FLOAT) + bondo_proxy_dofloat(*pp, ap->a_w.w_float, 0); + else if (ap->a_type == A_SYMBOL) + bondo_proxy_dosymbol(*pp, ap->a_w.w_symbol, 0); + else if (ap->a_type == A_POINTER) + bondo_proxy_dopointer(*pp, ap->a_w.w_gpointer, 0); + } + if (s) + bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[startid], s, 0); + if (doit) bondo_arm(x); +} + +static void bondo_proxy_domultiatom(t_bondo_proxy *x, + int ac, t_atom *av, int doit) +{ + if (ac > x->p_size) + { + /* LATER consider using BONDO_MAXSIZE (and warning if exceeded) */ + x->p_message = grow_nodata(&ac, &x->p_size, x->p_message, + BONDO_INISIZE, x->p_messini, + sizeof(*x->p_message)); + } + x->p_natoms = ac; + memcpy(x->p_message, av, ac * sizeof(*x->p_message)); + if (doit) bondo_arm(x->p_master); +} + +static void bondo_proxy_dolist(t_bondo_proxy *x, int ac, t_atom *av, int doit) +{ + if (x->p_master->x_multiatom) + { + x->p_selector = &s_list; + bondo_proxy_domultiatom(x, ac, av, doit); + } + else bondo_distribute(x->p_master, x->p_id, 0, ac, av, doit); +} + +static void bondo_proxy_list(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_dolist(x, ac, av, 1); +} + +static void bondo_proxy_doanything(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av, int doit) +{ + if (x->p_master->x_multiatom) + { + /* LATER rethink and CHECKME */ + if (s == &s_symbol) + { + if (ac && av->a_type == A_SYMBOL) + bondo_proxy_dosymbol(x, av->a_w.w_symbol, doit); + else + bondo_proxy_dosymbol(x, &s_symbol, doit); + } + else + { + x->p_selector = s; + bondo_proxy_domultiatom(x, ac, av, doit); + } + } + else bondo_distribute(x->p_master, x->p_id, s, ac, av, doit); +} + +static void bondo_proxy_anything(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_doanything(x, s, ac, av, 1); +} + +static void bondo_proxy_set(t_bondo_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + if (av->a_type == A_FLOAT) + { + if (ac > 1) + bondo_proxy_dolist(x, ac, av, 0); + else + bondo_proxy_dofloat(x, av->a_w.w_float, 0); + } + else if (av->a_type == A_SYMBOL) + /* CHECKED: no tests for 'set float ...' and 'set list...' -- + the parsing is made in an output routine */ + bondo_proxy_doanything(x, av->a_w.w_symbol, ac-1, av+1, 0); + else if (av->a_type == A_POINTER) + bondo_proxy_dopointer(x, av->a_w.w_gpointer, 0); + } + /* CHECKED: 'set' without arguments makes a slot inactive, + if multiatom, but is ignored, if !multiatom */ + else if (x->p_master->x_multiatom) x->p_selector = 0; +} + +static void bondo_bang(t_bondo *x) +{ + bondo_proxy_bang((t_bondo_proxy *)x->x_proxies[0]); +} + +static void bondo_float(t_bondo *x, t_float f) +{ + bondo_proxy_dofloat((t_bondo_proxy *)x->x_proxies[0], f, 1); +} + +static void bondo_symbol(t_bondo *x, t_symbol *s) +{ + bondo_proxy_dosymbol((t_bondo_proxy *)x->x_proxies[0], s, 1); +} + +static void bondo_pointer(t_bondo *x, t_gpointer *gp) +{ + bondo_proxy_dopointer((t_bondo_proxy *)x->x_proxies[0], gp, 1); +} + +static void bondo_list(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_dolist((t_bondo_proxy *)x->x_proxies[0], ac, av, 1); +} + +static void bondo_anything(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_doanything((t_bondo_proxy *)x->x_proxies[0], s, ac, av, 1); +} + +static void bondo_set(t_bondo *x, t_symbol *s, int ac, t_atom *av) +{ + bondo_proxy_set((t_bondo_proxy *)x->x_proxies[0], s, ac, av); +} + +static void bondo_free(t_bondo *x) +{ + if (x->x_clock) clock_free(x->x_clock); + if (x->x_proxies) + { + int i = x->x_nslots; + while (i--) + { + t_bondo_proxy *y = (t_bondo_proxy *)x->x_proxies[i]; + if (y->p_message != y->p_messini) + freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); + pd_free((t_pd *)y); + } + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } + if (x->x_outs) + freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs)); +} + +static void *bondo_new(t_symbol *s, int ac, t_atom *av) +{ + t_bondo *x; + int i, nslots, nproxies = BONDO_MINSLOTS; + int multiatom = 0; + t_float delay = 0; + t_pd **proxies; + t_outlet **outs; + i = 0; + while (ac--) + { + /* CHECKED: no warnings */ + if (av->a_type == A_FLOAT) + { + if (i == 0) + nproxies = (int)av->a_w.w_float; + else if (i == 1) + delay = av->a_w.w_float; + i++; + } + else if (av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == gensym("n")) multiatom = 1; + /* CHECKED: 'n' has to be the last argument given; + the arguments after any symbol are silently ignored -- + LATER decide if we should comply and break here */ + } + av++; + } + if (nproxies < BONDO_MINSLOTS) + nproxies = BONDO_MINSLOTS; + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + return (0); + for (nslots = 0; nslots < nproxies; nslots++) + if (!(proxies[nslots] = pd_new(bondo_proxy_class))) break; + if (nslots < BONDO_MINSLOTS + || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs)))) + { + i = nslots; + while (i--) pd_free(proxies[i]); + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_bondo *)pd_new(bondo_class); + x->x_delay = delay; + x->x_multiatom = multiatom; + x->x_nslots = nslots; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + x->x_outs = outs; + for (i = 0; i < nslots; i++) + { + t_bondo_proxy *y = (t_bondo_proxy *)proxies[i]; + y->p_master = x; + y->p_id = i; + y->p_selector = &s_float; /* CHECKED: it is so in multiatom mode too */ + y->p_float = 0; + y->p_symbol = 0; + y->p_pointer = 0; + y->p_size = BONDO_INISIZE; + y->p_natoms = 0; + y->p_message = y->p_messini; + if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); + x->x_outs[i] = outlet_new((t_object *)x, &s_anything); + } + x->x_clock = clock_new(x, (t_method)bondo_doit); + return (x); +} + +void bondo_setup(void) +{ + bondo_class = class_new(gensym("bondo"), + (t_newmethod)bondo_new, + (t_method)bondo_free, + sizeof(t_bondo), 0, A_GIMME, 0); + class_addbang(bondo_class, bondo_bang); + class_addfloat(bondo_class, bondo_float); + class_addsymbol(bondo_class, bondo_symbol); + class_addpointer(bondo_class, bondo_pointer); + class_addlist(bondo_class, bondo_list); + class_addanything(bondo_class, bondo_anything); + class_addmethod(bondo_class, (t_method)bondo_set, + gensym("set"), A_GIMME, 0); + bondo_proxy_class = class_new(gensym("_bondo_proxy"), 0, 0, + sizeof(t_bondo_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(bondo_proxy_class, bondo_proxy_bang); + class_addfloat(bondo_proxy_class, bondo_proxy_float); + class_addsymbol(bondo_proxy_class, bondo_proxy_symbol); + class_addpointer(bondo_proxy_class, bondo_proxy_pointer); + class_addlist(bondo_proxy_class, bondo_proxy_list); + class_addanything(bondo_proxy_class, bondo_proxy_anything); + class_addmethod(bondo_proxy_class, (t_method)bondo_proxy_set, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/buddy.c b/cyclone/hammer/buddy.c new file mode 100644 index 0000000..f272739 --- /dev/null +++ b/cyclone/hammer/buddy.c @@ -0,0 +1,253 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER compare with buddy.c from max sdk */ +/* LATER revisit buffer handling (maxsize, reentrancy) */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define BUDDY_MINSLOTS 2 +#define BUDDY_INISIZE 4 /* LATER rethink */ + +typedef struct _buddy +{ + t_object x_ob; + int x_nslots; + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; + t_outlet **x_outs; +} t_buddy; + +typedef struct _buddy_proxy +{ + t_object p_ob; + t_buddy *p_master; + t_symbol *p_selector; + t_float p_float; + t_symbol *p_symbol; + t_gpointer *p_pointer; + int p_size; /* as allocated */ + int p_natoms; /* as used */ + t_atom *p_message; + t_atom p_messini[BUDDY_INISIZE]; +} t_buddy_proxy; + +static t_class *buddy_class; +static t_class *buddy_proxy_class; + +static void buddy_clear(t_buddy *x) +{ + t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies; + int i = x->x_nslots; + while (i--) + { + (*p)->p_selector = 0; + (*p++)->p_natoms = 0; /* defensive */ + } +} + +static void buddy_check(t_buddy *x) +{ + t_buddy_proxy **p = (t_buddy_proxy **)x->x_proxies; + int i = x->x_nslots; + while (i--) + if (!(*p++)->p_selector) + return; + p = (t_buddy_proxy **)x->x_proxies; + i = x->x_nslots; + while (i--) + { + t_symbol *s = p[i]->p_selector; + if (s == &s_bang) + outlet_bang(x->x_outs[i]); + else if (s == &s_float) + outlet_float(x->x_outs[i], p[i]->p_float); + else if (s == &s_symbol && p[i]->p_symbol) + outlet_symbol(x->x_outs[i], p[i]->p_symbol); + else if (s == &s_pointer) + { + /* LATER */ + } + else if (s == &s_list) + outlet_list(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + else if (s) + outlet_anything(x->x_outs[i], s, p[i]->p_natoms, p[i]->p_message); + } + buddy_clear(x); +} + +static void buddy_proxy_bang(t_buddy_proxy *x) +{ + x->p_selector = &s_bang; + x->p_natoms = 0; /* defensive */ + buddy_check(x->p_master); +} + +static void buddy_proxy_float(t_buddy_proxy *x, t_float f) +{ + x->p_selector = &s_float; + x->p_float = f; + x->p_natoms = 0; /* defensive */ + buddy_check(x->p_master); +} + +static void buddy_proxy_symbol(t_buddy_proxy *x, t_symbol *s) +{ + x->p_selector = &s_symbol; + x->p_symbol = s; + x->p_natoms = 0; /* defensive */ + buddy_check(x->p_master); +} + +static void buddy_proxy_pointer(t_buddy_proxy *x, t_gpointer *gp) +{ + x->p_selector = &s_pointer; + x->p_pointer = gp; + x->p_natoms = 0; /* defensive */ + buddy_check(x->p_master); +} + +static void buddy_proxy_domessage(t_buddy_proxy *x, int ac, t_atom *av) +{ + if (ac > x->p_size) + { + /* LATER consider using BUDDY_MAXSIZE (and warning if exceeded) */ + x->p_message = grow_nodata(&ac, &x->p_size, x->p_message, + BUDDY_INISIZE, x->p_messini, + sizeof(*x->p_message)); + } + x->p_natoms = ac; + memcpy(x->p_message, av, ac * sizeof(*x->p_message)); + buddy_check(x->p_master); +} + +static void buddy_proxy_list(t_buddy_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + x->p_selector = &s_list; /* LATER rethink */ + buddy_proxy_domessage(x, ac, av); +} + +static void buddy_proxy_anything(t_buddy_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + x->p_selector = s; /* LATER rethink */ + buddy_proxy_domessage(x, ac, av); +} + +static void buddy_bang(t_buddy *x) +{ + buddy_proxy_bang((t_buddy_proxy *)x->x_proxies[0]); +} + +static void buddy_float(t_buddy *x, t_float f) +{ + buddy_proxy_float((t_buddy_proxy *)x->x_proxies[0], f); +} + +static void buddy_symbol(t_buddy *x, t_symbol *s) +{ + buddy_proxy_symbol((t_buddy_proxy *)x->x_proxies[0], s); +} + +static void buddy_pointer(t_buddy *x, t_gpointer *gp) +{ + buddy_proxy_pointer((t_buddy_proxy *)x->x_proxies[0], gp); +} + +static void buddy_list(t_buddy *x, t_symbol *s, int ac, t_atom *av) +{ + buddy_proxy_list((t_buddy_proxy *)x->x_proxies[0], s, ac, av); +} + +static void buddy_anything(t_buddy *x, t_symbol *s, int ac, t_atom *av) +{ + buddy_proxy_anything((t_buddy_proxy *)x->x_proxies[0], s, ac, av); +} + +static void buddy_free(t_buddy *x) +{ + if (x->x_proxies) + { + int i = x->x_nslots; + while (i--) + { + t_buddy_proxy *y = (t_buddy_proxy *)x->x_proxies[i]; + if (y->p_message != y->p_messini) + freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); + pd_free((t_pd *)y); + } + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } + if (x->x_outs) + freebytes(x->x_outs, x->x_nslots * sizeof(*x->x_outs)); +} + +static void *buddy_new(t_floatarg f) +{ + t_buddy *x; + int i, nslots, nproxies = (int)f; + t_pd **proxies; + t_outlet **outs; + if (nproxies < BUDDY_MINSLOTS) + nproxies = BUDDY_MINSLOTS; + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + return (0); + for (nslots = 0; nslots < nproxies; nslots++) + if (!(proxies[nslots] = pd_new(buddy_proxy_class))) break; + if (nslots < BUDDY_MINSLOTS + || !(outs = (t_outlet **)getbytes(nslots * sizeof(*outs)))) + { + int i = nslots; + while (i--) pd_free(proxies[i]); + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_buddy *)pd_new(buddy_class); + x->x_nslots = nslots; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + x->x_outs = outs; + for (i = 0; i < nslots; i++) + { + t_buddy_proxy *y = (t_buddy_proxy *)proxies[i]; + y->p_master = x; + y->p_selector = 0; + y->p_float = 0; + y->p_symbol = 0; + y->p_pointer = 0; + y->p_size = BUDDY_INISIZE; + y->p_natoms = 0; + y->p_message = y->p_messini; + if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); + x->x_outs[i] = outlet_new((t_object *)x, &s_anything); + } + return (x); +} + +void buddy_setup(void) +{ + buddy_class = class_new(gensym("buddy"), + (t_newmethod)buddy_new, + (t_method)buddy_free, + sizeof(t_buddy), 0, A_DEFFLOAT, 0); + class_addbang(buddy_class, buddy_bang); + class_addfloat(buddy_class, buddy_float); + class_addsymbol(buddy_class, buddy_symbol); + class_addpointer(buddy_class, buddy_pointer); + class_addlist(buddy_class, buddy_list); + class_addanything(buddy_class, buddy_anything); + class_addmethod(buddy_class, (t_method)buddy_clear, gensym("clear"), 0); + buddy_proxy_class = class_new(gensym("_buddy_proxy"), 0, 0, + sizeof(t_buddy_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(buddy_proxy_class, buddy_proxy_bang); + class_addfloat(buddy_proxy_class, buddy_proxy_float); + class_addsymbol(buddy_proxy_class, buddy_proxy_symbol); + class_addpointer(buddy_proxy_class, buddy_proxy_pointer); + class_addlist(buddy_proxy_class, buddy_proxy_list); + class_addanything(buddy_proxy_class, buddy_proxy_anything); +} diff --git a/cyclone/hammer/capture.c b/cyclone/hammer/capture.c new file mode 100644 index 0000000..b36c421 --- /dev/null +++ b/cyclone/hammer/capture.c @@ -0,0 +1,291 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "common/loud.h" +#include "hammer/file.h" + +#define CAPTURE_DEFSIZE 512 + +typedef struct _capture +{ + t_object x_ob; + t_canvas *x_canvas; + char x_intmode; /* if nonzero ('x' or 'm') floats are ignored */ + float *x_buffer; + int x_bufsize; + int x_count; + int x_head; + t_hammerfile *x_filehandle; +} t_capture; + +static t_class *capture_class; + +static void capture_float(t_capture *x, t_float f) +{ + if (x->x_intmode && f != (int)f) /* CHECKME float */ + return; + x->x_buffer[x->x_head++] = f; + if (x->x_head >= x->x_bufsize) + x->x_head = 0; + if (x->x_count < x->x_bufsize) + x->x_count++; +} + +static void capture_list(t_capture *x, t_symbol *s, int ac, t_atom *av) +{ + while (ac--) + { + if (av->a_type == A_FLOAT) /* CHECKME */ + capture_float(x, av->a_w.w_float); + av++; + } +} + +static void capture_clear(t_capture *x) +{ + x->x_count = 0; + x->x_head = 0; +} + +static void capture_count(t_capture *x) +{ + post("capture: %d items received", /* CHECKED */ + x->x_count); /* CHECKED incompatible (4.07 seems buggy here) */ +} + +static void capture_dump(t_capture *x) +{ + int count = x->x_count; + if (count < x->x_bufsize) + { + float *bp = x->x_buffer; + while (count--) + outlet_float(((t_object *)x)->ob_outlet, *bp++); + } + else + { + float *bp = x->x_buffer + x->x_head; + count = x->x_bufsize - x->x_head; + while (count--) + outlet_float(((t_object *)x)->ob_outlet, *bp++); + bp = x->x_buffer; + count = x->x_head; + while (count--) + outlet_float(((t_object *)x)->ob_outlet, *bp++); + } +} + +static int capture_formatint(int i, char *buf, int col, + int maxcol, char *fmt) +{ + char *bp = buf; + int cnt = 0; + if (col > 0) + *bp++ = ' ', cnt++; + cnt += sprintf(bp, fmt, i); + if (col + cnt > maxcol) + buf[0] = '\n', col = cnt; + else + col += cnt; + return (col); +} + +static int capture_formatfloat(float f, char *buf, int col, + int maxcol, char *fmt) +{ + char *bp = buf; + int cnt = 0; + if (col > 0) + *bp++ = ' ', cnt++; + cnt += sprintf(bp, fmt, f); + if (col + cnt > maxcol) + buf[0] = '\n', col = cnt; + else + col += cnt; + return (col); +} + +static int capture_formatnumber(t_capture *x, float f, char *buf, + int col, int maxcol) +{ + char intmode = x->x_intmode; + if (intmode == 'm') + intmode = (f < 128 && f > -128 ? 'd' : 'x'); /* CHECKME */ + if (intmode == 'x') + col = capture_formatint((int)f, buf, col, maxcol, "%x"); + else if (intmode) + col = capture_formatint((int)f, buf, col, maxcol, "%d"); + else + col = capture_formatfloat(f, buf, col, maxcol, "%g"); + return (col); +} + +static int capture_writefloat(t_capture *x, float f, char *buf, int col, + FILE *fp) +{ + /* CHECKED no linebreaks (FIXME) */ + col = capture_formatnumber(x, f, buf, col, 80); + return (fputs(buf, fp) < 0 ? -1 : col); +} + +static void capture_dowrite(t_capture *x, t_symbol *fn) +{ + FILE *fp = 0; + int count = x->x_count; + char buf[MAXPDSTRING]; + canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); + if (fp = fopen(buf, "w")) /* LATER ask if overwriting, CHECKED */ + { + int col = 0; + if (count < x->x_bufsize) + { + float *bp = x->x_buffer; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + } + else + { + float *bp = x->x_buffer + x->x_head; + count = x->x_bufsize - x->x_head; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + bp = x->x_buffer; + count = x->x_head; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + } + if (col) fputc('\n', fp); + fclose(fp); + return; + } +fail: + if (fp) fclose(fp); + loud_syserror((t_pd *)x, 0); +} + +static void capture_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + capture_dowrite((t_capture *)z, fn); +} + +static void capture_write(t_capture *x, t_symbol *s) +{ + if (s && s != &s_) + capture_dowrite(x, s); + else + hammerpanel_save(x->x_filehandle, 0, 0); +} + +static int capture_appendfloat(t_capture *x, float f, char *buf, int col) +{ + /* CHECKED 80 columns */ + col = capture_formatnumber(x, f, buf, col, 80); + hammereditor_append(x->x_filehandle, buf); + return (col); +} + +static void capture_open(t_capture *x) +{ + int count = x->x_count; + char buf[MAXPDSTRING]; + hammereditor_open(x->x_filehandle, "t_capture"); /* CHECKED */ + if (count < x->x_bufsize) + { + float *bp = x->x_buffer; + int col = 0; + while (count--) + col = capture_appendfloat(x, *bp++, buf, col); + } + else + { + float *bp = x->x_buffer + x->x_head; + int col = 0; + count = x->x_bufsize - x->x_head; + while (count--) + col = capture_appendfloat(x, *bp++, buf, col); + bp = x->x_buffer; + count = x->x_head; + while (count--) + col = capture_appendfloat(x, *bp++, buf, col); + } +} + +/* CHECKED without asking and storing the changes */ +static void capture_wclose(t_capture *x) +{ + hammereditor_close(x->x_filehandle, 0); +} + +static void capture_click(t_capture *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + capture_open(x); +} + +static void capture_free(t_capture *x) +{ + hammerfile_free(x->x_filehandle); + if (x->x_buffer) + freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer)); +} + +static void *capture_new(t_symbol *s, t_floatarg f) +{ + t_capture *x = 0; + float *buffer; + int bufsize = (int)f; /* CHECKME */ + if (bufsize <= 0) /* CHECKME */ + bufsize = CAPTURE_DEFSIZE; + if (buffer = getbytes(bufsize * sizeof(*buffer))) + { + x = (t_capture *)pd_new(capture_class); + x->x_canvas = canvas_getcurrent(); + if (s && s != &s_) + { + if (s == gensym("x")) + x->x_intmode = 'x'; + else if (s == gensym("m")) + x->x_intmode = 'm'; + else + x->x_intmode = 'd'; /* ignore floats */ + } + x->x_buffer = buffer; + x->x_bufsize = bufsize; + outlet_new((t_object *)x, &s_float); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, capture_writehook, 0); + capture_clear(x); + } + return (x); +} + +void capture_setup(void) +{ + capture_class = class_new(gensym("capture"), + (t_newmethod)capture_new, + (t_method)capture_free, + sizeof(t_capture), 0, A_DEFFLOAT, A_DEFSYM, 0); + class_addfloat(capture_class, capture_float); + class_addlist(capture_class, capture_list); + class_addmethod(capture_class, (t_method)capture_clear, + gensym("clear"), 0); + class_addmethod(capture_class, (t_method)capture_count, + gensym("count"), 0); + class_addmethod(capture_class, (t_method)capture_dump, + gensym("dump"), 0); + class_addmethod(capture_class, (t_method)capture_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(capture_class, (t_method)capture_open, + gensym("open"), 0); + class_addmethod(capture_class, (t_method)capture_wclose, + gensym("wclose"), 0); + class_addmethod(capture_class, (t_method)capture_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(capture_class, 0); +} diff --git a/cyclone/hammer/cartopol.c b/cyclone/hammer/cartopol.c new file mode 100644 index 0000000..4200686 --- /dev/null +++ b/cyclone/hammer/cartopol.c @@ -0,0 +1,44 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define atan2f atan2 +#define hypotf hypot +#endif + +typedef struct _cartopol +{ + t_object x_ob; + t_float x_imag; + t_outlet *x_out2; +} t_cartopol; + +static t_class *cartopol_class; + +static void cartopol_float(t_cartopol *x, t_float f) +{ + outlet_float(x->x_out2, atan2f(x->x_imag, f)); + outlet_float(((t_object *)x)->ob_outlet, hypotf(f, x->x_imag)); +} + +static void *cartopol_new(void) +{ + t_cartopol *x = (t_cartopol *)pd_new(cartopol_class); + floatinlet_new((t_object *)x, &x->x_imag); + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void cartopol_setup(void) +{ + cartopol_class = class_new(gensym("cartopol"), + (t_newmethod)cartopol_new, 0, + sizeof(t_cartopol), 0, 0); + class_addfloat(cartopol_class, cartopol_float); +} diff --git a/cyclone/hammer/coll.c b/cyclone/hammer/coll.c new file mode 100644 index 0000000..c4a3388 --- /dev/null +++ b/cyclone/hammer/coll.c @@ -0,0 +1,1597 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "hammer/file.h" + +/* FIXME sort crashes after (corrupt?) transfers from the editor */ +/* LATER make sure that ``reentrancy protection hack'' is really working... */ +/* CHECKME default fname for 'write' -- c_filename, x_name, nothing? */ + +#define COLL_DEBUG + +typedef struct _collelem +{ + int e_hasnumkey; + int e_numkey; + t_symbol *e_symkey; + struct _collelem *e_prev; + struct _collelem *e_next; + int e_size; + t_atom *e_data; +} t_collelem; + +typedef struct _collcommon +{ + t_pd c_pd; + struct _coll *c_refs; /* used in read-banging and dirty flag handling */ + int c_embedflag; /* common field (CHECKED in 'TEXT') */ + int c_loading; + int c_relinked; + int c_selfmodified; + int c_entered; /* a counter, LATER rethink */ + t_symbol *c_filename; + t_canvas *c_lastcanvas; + t_hammerfile *c_filehandle; + t_collelem *c_first; + t_collelem *c_last; + t_collelem *c_ahead; + t_collelem *c_back; +} t_collcommon; + +typedef struct _coll +{ + t_object x_ob; + t_canvas *x_canvas; + t_symbol *x_name; + t_collcommon *x_common; + t_hammerfile *x_filehandle; + t_outlet *x_keyout; + t_outlet *x_filebangout; + t_outlet *x_dumpbangout; + struct _coll *x_next; +} t_coll; + +static t_class *coll_class; +static t_class *collcommon_class; + +static t_collelem *collelem_new(int ac, t_atom *av, int *np, t_symbol *s) +{ + t_collelem *ep = (t_collelem *)getbytes(sizeof(*ep)); + if (ep->e_hasnumkey = (np != 0)) + ep->e_numkey = *np; + ep->e_symkey = s; + ep->e_prev = ep->e_next = 0; + if (ep->e_size = ac) + { + t_atom *ap = getbytes(ac * sizeof(*ap)); + ep->e_data = ap; + if (av) while (ac--) + *ap++ = *av++; + else while (ac--) + { + SETFLOAT(ap, 0); + ap++; + } + } + else ep->e_data = 0; + return (ep); +} + +static void collelem_free(t_collelem *ep) +{ + if (ep->e_data) + freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data)); + freebytes(ep, sizeof(*ep)); +} + +/* CHECKME again... apparently c74 is not able to fix this for good */ +/* result: 1 for ep1 < ep2, otherwise 0 (symbols are less then floats) */ +static int collelem_less(t_collelem *ep1, t_collelem *ep2, int ndx) +{ + if (ndx < 0) + { + if (ep1->e_symkey) + return (ep2->e_symkey ? + strcmp(ep1->e_symkey->s_name, + ep2->e_symkey->s_name) < 0 + : 1); /* CHECKED incompatible with 4.07, but consistent */ + else if (ep2->e_symkey) + return (0); /* CHECKED incompatible with 4.07, but consistent */ + else + return (ep1->e_numkey < ep2->e_numkey); /* CHECKED in 4.07 */ + } + else + { + t_atom *ap1 = (ndx < ep1->e_size ? + ep1->e_data + ndx : ep1->e_data + ep1->e_size - 1); + t_atom *ap2 = (ndx < ep2->e_size ? + ep2->e_data + ndx : ep2->e_data + ep2->e_size - 1); + if (ap1->a_type == A_FLOAT) + { + if (ap2->a_type == A_FLOAT) + return (ap1->a_w.w_float < ap2->a_w.w_float); + else if (ap2->a_type == A_SYMBOL) + return (0); + else + return (1); + } + else if (ap1->a_type == A_SYMBOL) + { + if (ap2->a_type == A_FLOAT) + return (1); + else if (ap2->a_type == A_SYMBOL) + return (strcmp(ap1->a_w.w_symbol->s_name, + ap2->a_w.w_symbol->s_name) < 0); + else + return (1); + } + else + return (0); + } +} + +static void collelem_post(t_collelem *ep) +{ + if (ep->e_hasnumkey && ep->e_symkey) + startpost("%d %s:", ep->e_numkey, ep->e_symkey->s_name); + else if (ep->e_hasnumkey) + startpost("%d:", ep->e_numkey); + else if (ep->e_symkey) + startpost("%s:", ep->e_symkey->s_name); + else bug("collcommon_post"); + postatom(ep->e_size, ep->e_data); + endpost(); +} + +static void collcommon_post(t_collcommon *cc) +{ + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) collelem_post(ep); +} + +static t_collelem *collcommon_numkey(t_collcommon *cc, int numkey) +{ + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + if (ep->e_hasnumkey && ep->e_numkey == numkey) + return (ep); + return (0); +} + +static t_collelem *collcommon_symkey(t_collcommon *cc, t_symbol *symkey) +{ + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + if (ep->e_symkey == symkey) + return (ep); + return (0); +} + +static void collcommon_takeout(t_collcommon *cc, t_collelem *ep) +{ + if (ep->e_prev) + ep->e_prev->e_next = ep->e_next; + else + cc->c_first = ep->e_next; + if (ep->e_next) + ep->e_next->e_prev = ep->e_prev; + else + cc->c_last = ep->e_prev; + if (cc->c_ahead == ep) + cc->c_ahead = ep->e_next; + if (cc->c_back == ep) + cc->c_back = ep->e_prev; +} + +static void collcommon_modified(t_collcommon *cc, int relinked) +{ + if (cc->c_loading) + return; + if (relinked) + { + cc->c_relinked = 1; + } + if (cc->c_embedflag) + { + t_coll *x; + for (x = cc->c_refs; x; x = x->x_next) + if (x->x_canvas && glist_isvisible(x->x_canvas)) + canvas_dirty(x->x_canvas, 1); + } +} + +/* atomic collcommon modifiers: clearall, remove, replace, + putbefore, putafter, swaplinks, swapkeys, changesymkey, renumber, sort */ + +static void collcommon_clearall(t_collcommon *cc) +{ + if (cc->c_first) + { + t_collelem *ep1 = cc->c_first, *ep2; + do + { + ep2 = ep1->e_next; + collelem_free(ep1); + } + while (ep1 = ep2); + cc->c_first = cc->c_last = 0; + cc->c_ahead = cc->c_back = 0; + collcommon_modified(cc, 1); + } +} + +static void collcommon_remove(t_collcommon *cc, t_collelem *ep) +{ + collcommon_takeout(cc, ep); + collelem_free(ep); + collcommon_modified(cc, 1); +} + +static void collcommon_replace(t_collcommon *cc, t_collelem *ep, + int ac, t_atom *av, int *np, t_symbol *s) +{ + if (ep->e_hasnumkey = (np != 0)) + ep->e_numkey = *np; + ep->e_symkey = s; + if (ac) + { + int i = ac; + t_atom *ap; + if (ep->e_data) + { + if (ep->e_size != ac) + ap = resizebytes(ep->e_data, + ep->e_size * sizeof(*ap), ac * sizeof(*ap)); + else ap = ep->e_data; + } + else + ap = getbytes(ac * sizeof(*ap)); + ep->e_data = ap; + if (av) while (i --) + *ap++ = *av++; + else while (i --) + { + SETFLOAT(ap, 0); + ap++; + } + } + else + { + if (ep->e_data) + freebytes(ep->e_data, ep->e_size * sizeof(*ep->e_data)); + ep->e_data = 0; + } + ep->e_size = ac; + collcommon_modified(cc, 0); +} + +static void collcommon_putbefore(t_collcommon *cc, + t_collelem *ep, t_collelem *next) +{ + if (next) + { + ep->e_next = next; + if (ep->e_prev = next->e_prev) + ep->e_prev->e_next = ep; + else + cc->c_first = ep; + next->e_prev = ep; + } + else if (cc->c_first || cc->c_last) + bug("collcommon_putbefore"); + else + cc->c_first = cc->c_last = ep; + collcommon_modified(cc, 1); +} + +static void collcommon_putafter(t_collcommon *cc, + t_collelem *ep, t_collelem *prev) +{ + if (prev) + { + ep->e_prev = prev; + if (ep->e_next = prev->e_next) + ep->e_next->e_prev = ep; + else + cc->c_last = ep; + prev->e_next = ep; + } + else if (cc->c_first || cc->c_last) + bug("collcommon_putafter"); + else + cc->c_first = cc->c_last = ep; + collcommon_modified(cc, 1); +} + +/* LATER consider making it faster, if there is a real need. + Now called only in the sort routine, once per sort. */ +static void collcommon_swaplinks(t_collcommon *cc, + t_collelem *ep1, t_collelem *ep2) +{ + if (ep1 != ep2) + { + t_collelem *prev1 = ep1->e_prev, *prev2 = ep2->e_prev; + if (prev1 == ep2) + { + collcommon_takeout(cc, ep2); + collcommon_putafter(cc, ep2, ep1); + } + else if (prev2 == ep1) + { + collcommon_takeout(cc, ep1); + collcommon_putafter(cc, ep1, ep2); + } + else if (prev1) + { + if (prev2) + { + collcommon_takeout(cc, ep1); + collcommon_takeout(cc, ep2); + collcommon_putafter(cc, ep1, prev2); + collcommon_putafter(cc, ep2, prev1); + } + else + { + t_collelem *next2 = ep2->e_next; + collcommon_takeout(cc, ep1); + collcommon_takeout(cc, ep2); + collcommon_putbefore(cc, ep1, next2); + collcommon_putafter(cc, ep2, prev1); + } + } + else if (prev2) + { + t_collelem *next1 = ep1->e_next; + collcommon_takeout(cc, ep1); + collcommon_takeout(cc, ep2); + collcommon_putafter(cc, ep1, prev2); + collcommon_putbefore(cc, ep2, next1); + } + else bug("collcommon_swaplinks"); + } +} + +static void collcommon_swapkeys(t_collcommon *cc, + t_collelem *ep1, t_collelem *ep2) +{ + int hasnumkey = ep2->e_hasnumkey, numkey = ep2->e_numkey; + t_symbol *symkey = ep2->e_symkey; + ep2->e_hasnumkey = ep1->e_hasnumkey; + ep2->e_numkey = ep1->e_numkey; + ep2->e_symkey = ep1->e_symkey; + ep1->e_hasnumkey = hasnumkey; + ep1->e_numkey = numkey; + ep1->e_symkey = symkey; + collcommon_modified(cc, 0); +} + +static void collcommon_changesymkey(t_collcommon *cc, + t_collelem *ep, t_symbol *s) +{ + ep->e_symkey = s; + collcommon_modified(cc, 0); +} + +static void collcommon_renumber(t_collcommon *cc, int startkey) +{ + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + if (ep->e_hasnumkey) + ep->e_numkey = startkey++; + collcommon_modified(cc, 0); +} + +/* LATER choose a better algo, after coll's storage structures stabilize. + Note, that even the simple insertion sort below (n-square) might prove + better for dlls, than theoretically efficient algo (nlogn) which requires + random access emulation. Avoiding recursion is not a bad idea, too. */ +static void collcommon_sort(t_collcommon *cc, int asc, int ndx) +{ + t_collelem *min = cc->c_first; + t_collelem *ep; + if (min && (ep = min->e_next)) + { + cc->c_loading = 1; + /* search for a sentinel element */ + do + if (collelem_less(ep, min, ndx) == asc) min = ep; + while (ep = ep->e_next); + /* prepend it */ + collcommon_swaplinks(cc, cc->c_first, min); + /* sort */ + ep = min->e_next->e_next; + while (ep) + { + t_collelem *next = ep->e_next; + for (min = ep->e_prev; + collelem_less(ep, min, ndx) == asc; + min = min->e_prev); + if (ep != min->e_next) + { + collcommon_takeout(cc, ep); + collcommon_putafter(cc, ep, min); + } + ep = next; + } + cc->c_loading = 0; + collcommon_modified(cc, 1); + } +} + +static void collcommon_adddata(t_collcommon *cc, t_collelem *ep, + int ac, t_atom *av) +{ + if (ac) + { + t_atom *ap; + int newsize = ep->e_size + ac; + if (ep->e_data) + ap = resizebytes(ep->e_data, + ep->e_size * sizeof(*ap), newsize * sizeof(*ap)); + else + { + ep->e_size = 0; /* redundant, hopefully */ + ap = getbytes(newsize * sizeof(*ap)); + } + ep->e_data = ap; + ap += ep->e_size; + if (av) while (ac--) + *ap++ = *av++; + else while (ac--) + { + SETFLOAT(ap, 0); + ap++; + } + ep->e_size = newsize; + collcommon_modified(cc, 0); + } +} + +static t_collelem *collcommon_tonumkey(t_collcommon *cc, int numkey, + int ac, t_atom *av, int replace) +{ + t_collelem *old = collcommon_numkey(cc, numkey), *new; + if (old && replace) + collcommon_replace(cc, new = old, ac, av, &numkey, 0); + else + { + new = collelem_new(ac, av, &numkey, 0); + if (old) + { + collcommon_putbefore(cc, new, old); + do + if (old->e_hasnumkey) old->e_numkey++; /* LATER rethink */ + while (old = old->e_next); + } + else + { + int closestkey = 0; /* LATER rethink */ + t_collelem *closest = 0, *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + { + if (ep->e_hasnumkey) + { + if (numkey >= closestkey && numkey <= ep->e_numkey) + { + collcommon_putbefore(cc, new, ep); + break; + } + closestkey = ep->e_numkey; + } + closest = ep; + } + if (!ep) + { + if (numkey <= closestkey) + collcommon_putbefore(cc, new, closest); + else + collcommon_putafter(cc, new, closest); + } + } + } + return (new); +} + +static t_collelem *collcommon_tosymkey(t_collcommon *cc, t_symbol *symkey, + int ac, t_atom *av, int replace) +{ + t_collelem *old = collcommon_symkey(cc, symkey), *new; + if (old && replace) + collcommon_replace(cc, new = old, ac, av, 0, symkey); + else + collcommon_putafter(cc, new = collelem_new(ac, av, 0, symkey), + cc->c_last); + return (new); +} + +static int collcommon_fromlist(t_collcommon *cc, int ac, t_atom *av) +{ + int hasnumkey = 0, numkey; + t_symbol *symkey = 0; + int size = 0; + t_atom *data = 0; + int nlines = 0; + cc->c_loading = 1; + collcommon_clearall(cc); + while (ac--) + { + if (data) + { + if (av->a_type == A_SEMI) + { + t_collelem *ep = collelem_new(size, data, + hasnumkey ? &numkey : 0, symkey); + collcommon_putafter(cc, ep, cc->c_last); + hasnumkey = 0; + symkey = 0; + data = 0; + nlines++; + } + if (av->a_type == A_COMMA) + { + /* CHECKED rejecting a comma */ + collcommon_clearall(cc); /* LATER rethink */ + cc->c_loading = 0; + return (-nlines); + } + else size++; + } + else if (av->a_type == A_COMMA) + { + size = 0; + data = av + 1; + } + else if (av->a_type == A_SYMBOL) + symkey = av->a_w.w_symbol; + else if (av->a_type == A_FLOAT && + loud_checkint(0, av->a_w.w_float, &numkey, 0)) + hasnumkey = 1; + else + { + loud_error(0, "coll: bad atom"); + collcommon_clearall(cc); /* LATER rethink */ + cc->c_loading = 0; + return (-nlines); + } + av++; + } + if (data) + { + loud_error(0, "coll: incomplete"); + collcommon_clearall(cc); /* LATER rethink */ + cc->c_loading = 0; + return (-nlines); + } + cc->c_loading = 0; + return (nlines); +} + +static int collcommon_frombinbuf(t_collcommon *cc, t_binbuf *bb) +{ + return (collcommon_fromlist(cc, binbuf_getnatom(bb), binbuf_getvec(bb))); +} + +static void collcommon_doread(t_collcommon *cc, t_symbol *fn, t_canvas *cv) +{ + t_binbuf *bb; + int ac; + t_atom *av; + char buf[MAXPDSTRING]; + if (!fn && !(fn = cc->c_filename)) /* !fn: 'readagain' */ + return; + if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'read' w/o arg, 'readagain' */ + canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); + else + { + strncpy(buf, fn->s_name, MAXPDSTRING); + buf[MAXPDSTRING-1] = 0; + } + if (!cc->c_refs) + { + /* loading during object creation -- + avoid binbuf_read()'s complaints, LATER rethink */ + FILE *fp; + char fname[MAXPDSTRING]; + sys_bashfilename(buf, fname); + if (!(fp = fopen(fname, "r"))) + { + loud_warning(&coll_class, "no coll file '%s'", fname); + return; + } + fclose(fp); + } + bb = binbuf_new(); + if (binbuf_read(bb, buf, "", 0)) + loud_error(0, "coll: error reading text file '%s'", fn->s_name); + else + { + int nlines = collcommon_frombinbuf(cc, bb); + if (nlines > 0) + { + t_coll *x; + /* LATER consider making this more robust */ + for (x = cc->c_refs; x; x = x->x_next) + outlet_bang(x->x_filebangout); + cc->c_lastcanvas = cv; + cc->c_filename = fn; + post("coll: finished reading %d lines from text file '%s'", + nlines, fn->s_name); + } + else if (nlines < 0) + loud_error(0, "coll: error in line %d of text file '%s'", + 1 - nlines, fn->s_name); + else + loud_error(0, "coll: error reading text file '%s'", fn->s_name); + if (cc->c_refs) + collcommon_modified(cc, 1); + } + binbuf_free(bb); +} + +static void collcommon_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + collcommon_doread((t_collcommon *)z, fn, 0); +} + +static void collcommon_tobinbuf(t_collcommon *cc, t_binbuf *bb) +{ + t_collelem *ep; + t_atom at[3]; + for (ep = cc->c_first; ep; ep = ep->e_next) + { + t_atom *ap = at; + int cnt = 1; + if (ep->e_hasnumkey) + { + SETFLOAT(ap, ep->e_numkey); + ap++; cnt++; + } + if (ep->e_symkey) + { + SETSYMBOL(ap, ep->e_symkey); + ap++; cnt++; + } + SETCOMMA(ap); + binbuf_add(bb, cnt, at); + binbuf_add(bb, ep->e_size, ep->e_data); + binbuf_addsemi(bb); + } +} + +static void collcommon_dowrite(t_collcommon *cc, t_symbol *fn, t_canvas *cv) +{ + t_binbuf *bb; + int ac; + t_atom *av; + char buf[MAXPDSTRING]; + if (!fn && !(fn = cc->c_filename)) /* !fn: 'writeagain' */ + return; + if (cv || (cv = cc->c_lastcanvas)) /* !cv: 'write' w/o arg, 'writeagain' */ + canvas_makefilename(cv, fn->s_name, buf, MAXPDSTRING); + else + { + strncpy(buf, fn->s_name, MAXPDSTRING); + buf[MAXPDSTRING-1] = 0; + } + bb = binbuf_new(); + collcommon_tobinbuf(cc, bb); + if (binbuf_write(bb, buf, "", 0)) + loud_error(0, "coll: error writing text file '%s'", fn->s_name); + else + { + cc->c_lastcanvas = cv; + cc->c_filename = fn; + } + binbuf_free(bb); +} + +static void collcommon_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + collcommon_dowrite((t_collcommon *)z, fn, 0); +} + +static void coll_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) +{ + t_coll *x = (t_coll *)z; + t_collcommon *cc = x->x_common; + if (cc->c_embedflag) + { + t_collelem *ep; + t_atom at[6]; + binbuf_addv(bb, "ssii;", bindsym, gensym("flags"), 1, 0); + SETSYMBOL(at, bindsym); + for (ep = cc->c_first; ep; ep = ep->e_next) + { + t_atom *ap = at + 1; + int cnt; + if (ep->e_hasnumkey && ep->e_symkey) + { + SETSYMBOL(ap, gensym("nstore")); + ap++; + SETSYMBOL(ap, ep->e_symkey); + ap++; + SETFLOAT(ap, ep->e_numkey); + cnt = 4; + } + else if (ep->e_symkey) + { + SETSYMBOL(ap, gensym("store")); + ap++; + SETSYMBOL(ap, ep->e_symkey); + cnt = 3; + } + else + { + SETFLOAT(ap, ep->e_numkey); + cnt = 2; + } + binbuf_add(bb, cnt, at); + binbuf_add(bb, ep->e_size, ep->e_data); + binbuf_addsemi(bb); + } + } +} + +static void collcommon_editorhook(t_pd *z, t_symbol *s, int ac, t_atom *av) +{ + int nlines = collcommon_fromlist((t_collcommon *)z, ac, av); + if (nlines < 0) + loud_error(0, "coll: editing error in line %d", 1 - nlines); +} + +static t_collcommon *coll_checkcommon(t_coll *x) +{ + if (x->x_name && + x->x_common != (t_collcommon *)pd_findbyclass(x->x_name, + collcommon_class)) + { + bug("coll_checkcommon"); + return (0); + } + return (x->x_common); +} + +static void coll_unbind(t_coll *x) +{ + /* LATER consider calling coll_checkcommon(x) */ + t_collcommon *cc = x->x_common; + t_coll *prev, *next; + if ((prev = cc->c_refs) == x) + { + if (!(cc->c_refs = x->x_next)) + { + hammerfile_free(cc->c_filehandle); + cc->c_loading = 1; /* disable dirty-flag handling, LATER rethink */ + collcommon_clearall(cc); + if (x->x_name) pd_unbind(&cc->c_pd, x->x_name); + pd_free(&cc->c_pd); + } + } + else if (prev) + { + while (next = prev->x_next) + { + if (next == x) + { + prev->x_next = next->x_next; + break; + } + prev = next; + } + } + x->x_common = 0; + x->x_name = 0; + x->x_next = 0; +} + +static void coll_bind(t_coll *x, t_symbol *name) +{ + t_collcommon *cc = 0; + if (name == &s_) + name = 0; + else if (name) + cc = (t_collcommon *)pd_findbyclass(name, collcommon_class); + if (!cc) + { + cc = (t_collcommon *)pd_new(collcommon_class); + cc->c_refs = 0; + cc->c_embedflag = 0; + cc->c_loading = 0; + if (name) + { + pd_bind(&cc->c_pd, name); + /* LATER rethink canvas unpredictability */ + collcommon_doread(cc, name, x->x_canvas); + } + else + { + cc->c_filename = 0; + cc->c_lastcanvas = 0; + } + cc->c_filehandle = hammerfile_new((t_pd *)cc, 0, collcommon_readhook, + collcommon_writehook, + collcommon_editorhook); + } + x->x_common = cc; + x->x_name = name; + x->x_next = cc->c_refs; + cc->c_refs = x; +} + +static int coll_rebind(t_coll *x, t_symbol *name) +{ + t_collcommon *cc; + if (name && name != &s_ && + (cc = (t_collcommon *)pd_findbyclass(name, collcommon_class))) + { + coll_unbind(x); + x->x_common = cc; + x->x_name = name; + x->x_next = cc->c_refs; + cc->c_refs = x; + return (1); + } + else return (0); +} + +static void coll_dooutput(t_coll *x, int ac, t_atom *av) +{ + if (ac > 1) + { + if (av->a_type == A_FLOAT) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else if (av->a_type == A_SYMBOL) + outlet_anything(((t_object *)x)->ob_outlet, + av->a_w.w_symbol, ac-1, av+1); + } + else if (ac) + { + if (av->a_type == A_FLOAT) + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); + } +} + +static void coll_keyoutput(t_coll *x, t_collelem *ep) +{ + t_collcommon *cc = x->x_common; + if (!cc->c_entered++) cc->c_selfmodified = 0; + cc->c_relinked = 0; + if (ep->e_hasnumkey) + outlet_float(x->x_keyout, ep->e_numkey); + else if (ep->e_symkey) + outlet_symbol(x->x_keyout, ep->e_symkey); + else + outlet_float(x->x_keyout, 0); + if (cc->c_relinked) cc->c_selfmodified = 1; + cc->c_entered--; +} + +static t_collelem *coll_findkey(t_coll *x, t_atom *key, t_symbol *mess) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep = 0; + if (key->a_type == A_FLOAT) + { + int numkey; + if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess)) + ep = collcommon_numkey(cc, numkey); + else + mess = 0; + } + else if (key->a_type == A_SYMBOL) + ep = collcommon_symkey(cc, key->a_w.w_symbol); + else if (mess) + { + loud_messarg((t_pd *)x, mess); + mess = 0; + } + if (!ep && mess) + loud_error((t_pd *)x, "no such key"); + return (ep); +} + +static t_collelem *coll_tokey(t_coll *x, t_atom *key, int ac, t_atom *av, + int replace, t_symbol *mess) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep = 0; + if (key->a_type == A_FLOAT) + { + int numkey; + if (loud_checkint((t_pd *)x, key->a_w.w_float, &numkey, mess)) + ep = collcommon_tonumkey(cc, numkey, ac, av, replace); + } + else if (key->a_type == A_SYMBOL) + ep = collcommon_tosymkey(cc, key->a_w.w_symbol, ac, av, replace); + else if (mess) + loud_messarg((t_pd *)x, mess); + return (ep); +} + +static t_collelem *coll_firsttyped(t_coll *x, int ndx, t_atomtype type) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + if (ep->e_size > ndx && ep->e_data[ndx].a_type == type) + return (ep); + return (0); +} + +/* the methods */ + +static void coll_float(t_coll *x, t_float f) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep; + int numkey; + if (loud_checkint((t_pd *)x, f, &numkey, &s_float) && + (ep = collcommon_numkey(cc, numkey))) + { + coll_keyoutput(x, ep); + if (!cc->c_selfmodified || (ep = collcommon_numkey(cc, numkey))) + coll_dooutput(x, ep->e_size, ep->e_data); + } +} + +static void coll_symbol(t_coll *x, t_symbol *s) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep; + if (ep = collcommon_symkey(cc, s)) + { + coll_keyoutput(x, ep); + if (!cc->c_selfmodified || (ep = collcommon_symkey(cc, s))) + coll_dooutput(x, ep->e_size, ep->e_data); + } +} + +static void coll_list(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av->a_type == A_FLOAT) + coll_tokey(x, av, ac-1, av+1, 1, &s_list); + else + loud_messarg((t_pd *)x, &s_list); +} + +static void coll_anything(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + coll_symbol(x, s); +} + +static void coll_store(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2) + coll_tokey(x, av, ac-1, av+1, 1, s); + else + loud_messarg((t_pd *)x, s); +} + +static void coll_nstore(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 3) + { + t_collcommon *cc = x->x_common; + t_collelem *ep; + int numkey; + if (av->a_type == A_FLOAT && av[1].a_type == A_SYMBOL) + { + if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s)) + { + if (ep = collcommon_symkey(cc, av[1].a_w.w_symbol)) + collcommon_remove(cc, ep); + ep = collcommon_tonumkey(cc, numkey, ac-2, av+2, 1); + ep->e_symkey = av[1].a_w.w_symbol; + } + } + else if (av->a_type == A_SYMBOL && av[1].a_type == A_FLOAT) + { + if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &numkey, s)) + { + if (ep = collcommon_numkey(cc, numkey)) + collcommon_remove(cc, ep); + ep = collcommon_tosymkey(cc, av->a_w.w_symbol, ac-2, av+2, 1); + ep->e_hasnumkey = 1; + ep->e_numkey = numkey; + } + } + else loud_messarg((t_pd *)x, s); + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_insert(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av->a_type == A_FLOAT) + coll_tokey(x, av, ac-1, av+1, 0, s); + else + loud_messarg((t_pd *)x, s); +} + +static void coll_remove(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_collelem *ep; + if (ep = coll_findkey(x, av, s)) + collcommon_remove(x->x_common, ep); + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_delete(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_collelem *ep; + if (ep = coll_findkey(x, av, s)) + { + if (av->a_type == A_FLOAT) + { + int numkey = ep->e_numkey; + t_collelem *next; + for (next = ep->e_next; next; next = next->e_next) + if (next->e_hasnumkey && next->e_numkey > numkey) + next->e_numkey--; + } + collcommon_remove(x->x_common, ep); + } + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_assoc(t_coll *x, t_symbol *s, t_floatarg f) +{ + int numkey; + if (loud_checkint((t_pd *)x, f, &numkey, gensym("assoc"))) + { + t_collcommon *cc = x->x_common; + t_collelem *ep1, *ep2; + if ((ep1 = collcommon_numkey(cc, numkey)) && + ep1->e_symkey != s) /* LATER rethink */ + { + if (ep2 = collcommon_symkey(cc, s)) + collcommon_remove(cc, ep2); + collcommon_changesymkey(cc, ep1, s); + } + } +} + +static void coll_deassoc(t_coll *x, t_symbol *s, t_floatarg f) +{ + int numkey; + if (loud_checkint((t_pd *)x, f, &numkey, gensym("deassoc"))) + { + t_collcommon *cc = x->x_common; + t_collelem *ep; + if (ep = collcommon_numkey(cc, numkey)) + collcommon_changesymkey(cc, ep, 0); + } +} + +static void coll_subsym(t_coll *x, t_symbol *s1, t_symbol *s2) +{ + t_collelem *ep; + if (s1 != s2 && (ep = collcommon_symkey(x->x_common, s2))) + collcommon_changesymkey(x->x_common, ep, s1); +} + +static void coll_renumber(t_coll *x, t_floatarg f) +{ + int startkey; + if (loud_checkint((t_pd *)x, f, &startkey, gensym("renumber"))) + collcommon_renumber(x->x_common, startkey); +} + +static void coll_merge(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2) + { + t_collcommon *cc = x->x_common; + t_collelem *ep; + if (av->a_type == A_FLOAT) + { + int numkey; + if (loud_checkint((t_pd *)x, av->a_w.w_float, &numkey, s)) + { + if (ep = collcommon_numkey(cc, numkey)) + collcommon_adddata(cc, ep, ac-1, av+1); + else /* LATER consider defining collcommon_toclosest() */ + collcommon_tonumkey(cc, numkey, ac-1, av+1, 1); + } + } + else if (av->a_type == A_SYMBOL) + { + if (ep = collcommon_symkey(cc, av->a_w.w_symbol)) + collcommon_adddata(cc, ep, ac-1, av+1); + else + { + ep = collelem_new(ac-1, av+1, 0, av->a_w.w_symbol); + collcommon_putafter(cc, ep, cc->c_last); + } + } + else loud_messarg((t_pd *)x, s); + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_sub(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_collelem *ep; + if (ep = coll_findkey(x, av, s)) + { + t_collcommon *cc = x->x_common; + t_atom *key = av++; + ac--; + while (ac >= 2) + { + if (av->a_type == A_FLOAT) + { + int ndx; + if (loud_checkint((t_pd *)x, av->a_w.w_float, &ndx, 0) + && ndx >= 1 && ndx <= ep->e_size) + ep->e_data[ndx-1] = av[1]; + } + ac -= 2; + av += 2; + } + if (s == gensym("sub")) + { + coll_keyoutput(x, ep); + if (!cc->c_selfmodified || (ep = coll_findkey(x, key, 0))) + coll_dooutput(x, ep->e_size, ep->e_data); + } + } + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_sort(t_coll *x, t_floatarg f1, t_floatarg f2) +{ + int dir, ndx; + if (loud_checkint((t_pd *)x, f1, &dir, gensym("sort")) && + loud_checkint((t_pd *)x, f2, &ndx, gensym("sort"))) + collcommon_sort(x->x_common, (dir < 0 ? 1 : 0), + (ndx < 0 ? -1 : (ndx ? ndx - 1 : 0))); +} + +static void coll_clear(t_coll *x) +{ + collcommon_clearall(x->x_common); +} + +/* According to the refman, the data should be swapped, rather than the keys + -- easy here, but apparently c74 people have chosen to avoid some effort + needed in case of their implementation... */ +static void coll_swap(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac == 2) + { + t_collelem *ep1, *ep2; + if ((ep1 = coll_findkey(x, av, s)) && + (ep2 = coll_findkey(x, av + 1, s))) + collcommon_swapkeys(x->x_common, ep1, ep2); + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_next(t_coll *x) +{ + t_collcommon *cc = x->x_common; + if (!cc->c_ahead && !(cc->c_ahead = cc->c_first)) + return; + coll_keyoutput(x, cc->c_ahead); + if (cc->c_selfmodified && !cc->c_ahead) + return; + coll_dooutput(x, cc->c_ahead->e_size, cc->c_ahead->e_data); + /* LATER think why c74 updates the heads prior to sendout + (it seems so clumsy...) */ + if (!cc->c_ahead && !(cc->c_ahead = cc->c_first)) + { + cc->c_back = 0; + return; + } + if (cc->c_ahead->e_next) + { + cc->c_ahead = cc->c_ahead->e_next; + if (!(cc->c_back = cc->c_ahead->e_prev)) /* LATER rethink */ + cc->c_back = cc->c_last; + } + else + { + /* CHECKED wraping */ + cc->c_back = cc->c_ahead; + cc->c_ahead = 0; + } +} + +static void coll_prev(t_coll *x) +{ + t_collcommon *cc = x->x_common; + if (!cc->c_back && !(cc->c_back = cc->c_last)) + return; + coll_keyoutput(x, cc->c_back); + if (cc->c_selfmodified && !cc->c_back) + return; + coll_dooutput(x, cc->c_back->e_size, cc->c_back->e_data); + /* LATER think why c74 updates the heads prior to sendout + (it seems so clumsy...) */ + if (!cc->c_back && !(cc->c_back = cc->c_last)) + { + cc->c_ahead = 0; + return; + } + if (cc->c_back->e_prev) + { + cc->c_back = cc->c_back->e_prev; + if (!(cc->c_ahead = cc->c_back->e_next)) /* LATER rethink */ + cc->c_ahead = cc->c_first; + } + else + { + /* CHECKED wraping */ + cc->c_ahead = cc->c_back; + cc->c_back = 0; + } +} + +static void coll_end(t_coll *x) +{ + t_collcommon *cc = x->x_common; + cc->c_back = cc->c_ahead = cc->c_last; +} + +static void coll_goto(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_collelem *ep = coll_findkey(x, av, s); + if (ep) + x->x_common->c_back = x->x_common->c_ahead = ep; + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_nth(t_coll *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av[1].a_type == A_FLOAT) + { + int ndx; + t_collelem *ep; + if (loud_checkint((t_pd *)x, av[1].a_w.w_float, &ndx, s) && + (ep = coll_findkey(x, av, s)) && + ep->e_size >= ndx) + { + t_atom *ap = ep->e_data + --ndx; + if (ap->a_type == A_FLOAT) + outlet_float(((t_object *)x)->ob_outlet, ap->a_w.w_float); + else if (ap->a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, ap->a_w.w_symbol); + } + } + else loud_messarg((t_pd *)x, s); +} + +static void coll_length(t_coll *x) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep = cc->c_first; + int result = 0; + while (ep) result++, ep = ep->e_next; + outlet_float(((t_object *)x)->ob_outlet, result); +} + +static void coll_min(t_coll *x, t_floatarg f) +{ + int ndx; + if (loud_checkint((t_pd *)x, f, &ndx, gensym("min"))) + { + t_collelem *found; + if (ndx <= 0) + ndx = 0; /* LATER consider complaining, CHECKME */ + else ndx--; + if (found = coll_firsttyped(x, ndx, A_FLOAT)) + { + t_float result = found->e_data[ndx].a_w.w_float; + t_collelem *ep; + for (ep = found->e_next; ep; ep = ep->e_next) + { + if (ep->e_size > ndx && + ep->e_data[ndx].a_type == A_FLOAT && + ep->e_data[ndx].a_w.w_float < result) + { + found = ep; + result = ep->e_data[ndx].a_w.w_float; + } + } + coll_keyoutput(x, found); + outlet_float(((t_object *)x)->ob_outlet, result); + } + } +} + +static void coll_max(t_coll *x, t_floatarg f) +{ + int ndx; + if (loud_checkint((t_pd *)x, f, &ndx, gensym("max"))) + { + t_collelem *found; + if (ndx <= 0) + ndx = 0; /* LATER consider complaining, CHECKME */ + else ndx--; + if (found = coll_firsttyped(x, ndx, A_FLOAT)) + { + t_float result = found->e_data[ndx].a_w.w_float; + t_collelem *ep; + for (ep = found->e_next; ep; ep = ep->e_next) + { + if (ep->e_size > ndx && + ep->e_data[ndx].a_type == A_FLOAT && + ep->e_data[ndx].a_w.w_float > result) + { + found = ep; + result = ep->e_data[ndx].a_w.w_float; + } + } + coll_keyoutput(x, found); + outlet_float(((t_object *)x)->ob_outlet, result); + } + } +} + +static void coll_refer(t_coll *x, t_symbol *s) +{ + if (!coll_rebind(x, s)) + { + /* LATER consider complaining */ + } +} + +static void coll_flags(t_coll *x, t_float f1, t_float f2) +{ + int i1; + if (loud_checkint((t_pd *)x, f1, &i1, gensym("flags"))) + { + t_collcommon *cc = x->x_common; + cc->c_embedflag = (i1 != 0); + } +} + +static void coll_read(t_coll *x, t_symbol *s) +{ + t_collcommon *cc = x->x_common; + if (s && s != &s_) + collcommon_doread(cc, s, x->x_canvas); + else + hammerpanel_open(cc->c_filehandle); +} + +static void coll_write(t_coll *x, t_symbol *s) +{ + t_collcommon *cc = x->x_common; + if (s && s != &s_) + collcommon_dowrite(cc, s, x->x_canvas); + else + hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKME default name */ +} + +static void coll_readagain(t_coll *x) +{ + t_collcommon *cc = x->x_common; + if (cc->c_filename) + collcommon_doread(cc, 0, 0); + else + hammerpanel_open(cc->c_filehandle); +} + +static void coll_writeagain(t_coll *x) +{ + t_collcommon *cc = x->x_common; + if (cc->c_filename) + collcommon_dowrite(cc, 0, 0); + else + hammerpanel_save(cc->c_filehandle, 0, 0); /* CHECKME default name */ +} + +static void coll_filetype(t_coll *x, t_symbol *s) +{ + /* dummy */ +} + +static void coll_dump(t_coll *x) +{ + t_collcommon *cc = x->x_common; + t_collelem *ep; + for (ep = cc->c_first; ep; ep = ep->e_next) + { + coll_keyoutput(x, ep); + if (cc->c_selfmodified) + break; + coll_dooutput(x, ep->e_size, ep->e_data); + } + outlet_bang(x->x_dumpbangout); +} + +static void coll_open(t_coll *x) +{ + t_collcommon *cc = x->x_common; + t_binbuf *bb = binbuf_new(); + int i, natoms, newline; + t_atom *ap; + char buf[MAXPDSTRING]; + /* LATER prepend "coll: " */ + hammereditor_open(cc->c_filehandle, + x->x_name ? x->x_name->s_name : "Untitled"); + collcommon_tobinbuf(cc, bb); + natoms = binbuf_getnatom(bb); + ap = binbuf_getvec(bb); + newline = 1; + while (natoms--) + { + char *ptr = buf; + if (ap->a_type != A_SEMI && ap->a_type != A_COMMA && !newline) + *ptr++ = ' '; + atom_string(ap, ptr, MAXPDSTRING); + if (ap->a_type == A_SEMI) + { + strcat(buf, "\n"); + newline = 1; + } + else newline = 0; + hammereditor_append(cc->c_filehandle, buf); + ap++; + } + binbuf_free(bb); +} + +/* asking and storing the changes -- CHECKME close window, and 'wclose' */ +static void coll_wclose(t_coll *x) +{ + hammereditor_close(x->x_common->c_filehandle, 1); +} + +static void coll_click(t_coll *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + coll_open(x); +} + +#ifdef COLL_DEBUG +static void coll_debug(t_coll *x, t_floatarg f) +{ + t_collcommon *cc = coll_checkcommon(x); + if (cc) + { + t_coll *x1 = cc->c_refs; + t_collelem *ep, *last; + int i = 0; + while (x1) i++, x1 = x1->x_next; + post("refcount %d", i); + for (ep = cc->c_first, last = 0; ep; ep = ep->e_next) last = ep; + if (last != cc->c_last) bug("coll_debug: last element"); + collcommon_post(cc); + } +} +#endif + +static void coll_free(t_coll *x) +{ + hammerfile_free(x->x_filehandle); + coll_unbind(x); +} + +static void *coll_new(t_symbol *s) +{ + t_coll *x = (t_coll *)pd_new(coll_class); + x->x_canvas = canvas_getcurrent(); + outlet_new((t_object *)x, &s_); + x->x_keyout = outlet_new((t_object *)x, &s_); + x->x_filebangout = outlet_new((t_object *)x, &s_bang); + x->x_dumpbangout = outlet_new((t_object *)x, &s_bang); + x->x_filehandle = hammerfile_new((t_pd *)x, coll_embedhook, 0, 0, 0); + coll_bind(x, s); + return (x); +} + +void coll_setup(void) +{ + coll_class = class_new(gensym("coll"), + (t_newmethod)coll_new, + (t_method)coll_free, + sizeof(t_coll), 0, A_DEFSYM, 0); + class_addbang(coll_class, coll_next); + class_addfloat(coll_class, coll_float); + class_addsymbol(coll_class, coll_symbol); + class_addlist(coll_class, coll_list); + class_addanything(coll_class, coll_anything); + class_addmethod(coll_class, (t_method)coll_store, + gensym("store"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_nstore, + gensym("nstore"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_insert, + gensym("insert"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_remove, + gensym("remove"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_delete, + gensym("delete"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_assoc, + gensym("assoc"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(coll_class, (t_method)coll_deassoc, + gensym("deassoc"), A_SYMBOL, A_FLOAT, 0); + class_addmethod(coll_class, (t_method)coll_subsym, + gensym("subsym"), A_SYMBOL, A_SYMBOL, 0); + class_addmethod(coll_class, (t_method)coll_renumber, + gensym("renumber"), A_DEFFLOAT, 0); + class_addmethod(coll_class, (t_method)coll_merge, + gensym("merge"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_sub, + gensym("sub"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_sub, + gensym("nsub"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_clear, + gensym("clear"), 0); + class_addmethod(coll_class, (t_method)coll_sort, + gensym("sort"), A_FLOAT, A_DEFFLOAT, 0); + class_addmethod(coll_class, (t_method)coll_swap, + gensym("swap"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_next, + gensym("next"), 0); + class_addmethod(coll_class, (t_method)coll_prev, + gensym("prev"), 0); + class_addmethod(coll_class, (t_method)coll_end, + gensym("end"), 0); + class_addmethod(coll_class, (t_method)coll_goto, + gensym("goto"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_nth, + gensym("nth"), A_GIMME, 0); + class_addmethod(coll_class, (t_method)coll_length, + gensym("length"), 0); + class_addmethod(coll_class, (t_method)coll_min, + gensym("min"), A_DEFFLOAT, 0); + class_addmethod(coll_class, (t_method)coll_max, + gensym("max"), A_DEFFLOAT, 0); + class_addmethod(coll_class, (t_method)coll_refer, + gensym("refer"), A_SYMBOL, 0); + class_addmethod(coll_class, (t_method)coll_flags, + gensym("flags"), A_FLOAT, A_FLOAT, 0); + class_addmethod(coll_class, (t_method)coll_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(coll_class, (t_method)coll_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(coll_class, (t_method)coll_readagain, + gensym("readagain"), 0); + class_addmethod(coll_class, (t_method)coll_writeagain, + gensym("writeagain"), 0); + class_addmethod(coll_class, (t_method)coll_filetype, + gensym("filetype"), A_SYMBOL, 0); + class_addmethod(coll_class, (t_method)coll_dump, + gensym("dump"), 0); + class_addmethod(coll_class, (t_method)coll_open, + gensym("open"), 0); + class_addmethod(coll_class, (t_method)coll_wclose, + gensym("wclose"), 0); + class_addmethod(coll_class, (t_method)coll_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); +#ifdef COLL_DEBUG + class_addmethod(coll_class, (t_method)coll_debug, + gensym("debug"), A_DEFFLOAT, 0); +#endif + hammerfile_setup(coll_class, 1); + collcommon_class = class_new(gensym("coll"), 0, 0, + sizeof(t_collcommon), CLASS_PD, 0); + /* this call is a nop (collcommon does not embed, and the hammerfile + class itself has been already set up above), but it is better to + have it around, just in case... */ + hammerfile_setup(collcommon_class, 0); +} diff --git a/cyclone/hammer/comment.c b/cyclone/hammer/comment.c new file mode 100644 index 0000000..e5cd5ab --- /dev/null +++ b/cyclone/hammer/comment.c @@ -0,0 +1,835 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME creation lag (X-specific) */ +/* LATER think about pushing text to the text editor (ctrl-t) + -- not easy, because we are not 'textedfor' */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" + +/* our proxy of the text_class (not in the API), LATER do not cheat */ +static t_class *makeshift_class; + +//#define COMMENT_DEBUG + +#define COMMENT_LMARGIN 1 +#define COMMENT_RMARGIN 1 +#define COMMENT_TMARGIN 2 +#define COMMENT_BMARGIN 2 +#define COMMENT_MINWIDTH 8 +#define COMMENT_HANDLEWIDTH 8 +#define COMMENT_OUTBUFSIZE 1000 + +typedef struct _comment +{ + t_object x_ob; + t_glist *x_glist; + t_canvas *x_canvas; /* also an 'isvised' flag */ + t_symbol *x_bindsym; + char x_tag[32]; + char x_texttag[32]; + char x_outlinetag[32]; + t_clock *x_transclock; + t_binbuf *x_binbuf; + char *x_textbuf; + int x_textbufsize; + int x_pixwidth; + int x_bbset; + int x_bbpending; + int x_x1; + int x_y1; + int x_x2; + int x_y2; + int x_newx2; + int x_dragon; + int x_fontsize; /* requested size */ + t_symbol *x_fontfamily; /* requested family */ + int x_fontprops; /* LATER pack weight and slant */ + t_symbol *x_encoding; /* requested encoding */ + unsigned char x_red; + unsigned char x_green; + unsigned char x_blue; + char x_color[8]; + int x_selstart; + int x_selend; + int x_active; + int x_ready; +} t_comment; + +static t_class *comment_class; +static t_class *commentsink_class; + +static t_pd *commentsink = 0; + +static void comment_draw(t_comment *x) +{ + char buf[COMMENT_OUTBUFSIZE], *outbuf, *outp; + int cvid = (int)x->x_canvas; + int reqsize = x->x_textbufsize + 350; /* FIXME estimation */ + if (reqsize > COMMENT_OUTBUFSIZE) + { +#ifdef COMMENT_DEBUG + post("allocating %d outbuf bytes", reqsize); +#endif + if (!(outbuf = getbytes(reqsize))) + return; + } + else outbuf = buf; + outp = outbuf; + if (x->x_encoding) + sprintf(outp, "set tt [comment_entext %s {%.*s}]\n", + x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf); + else + sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf); + outp += strlen(outp); + sprintf(outp, ".x%x.c create text %f %f -text $tt \ + -tags {%s %s} -font {%s %d} -fill %s", cvid, + (float)(text_xpix((t_text *)x, x->x_glist) + COMMENT_LMARGIN), + (float)(text_ypix((t_text *)x, x->x_glist) + COMMENT_TMARGIN), + x->x_texttag, x->x_tag, x->x_fontfamily->s_name, x->x_fontsize, + (glist_isselected(x->x_glist, &x->x_glist->gl_gobj) ? + "blue" : x->x_color)); + outp += strlen(outp); + if (x->x_pixwidth) + sprintf(outp, " -width %d -anchor nw\n", x->x_pixwidth); + else + strcpy(outp, " -anchor nw\n"); + outp += strlen(outp); + sprintf(outp, "comment_bbox %s .x%x.c %s\n", + x->x_bindsym->s_name, cvid, x->x_texttag); + outp += strlen(outp); + sprintf(outp, ".x%x.c bind %s <Button> {comment_click %s %%W %%x %%y %s}\n", + cvid, x->x_texttag, x->x_bindsym->s_name, x->x_texttag); + x->x_bbpending = 1; + sys_gui(outbuf); + if (outbuf != buf) freebytes(outbuf, reqsize); +} + +static void comment_update(t_comment *x) +{ + char buf[COMMENT_OUTBUFSIZE], *outbuf, *outp; + int cvid = (int)x->x_canvas; + int reqsize = x->x_textbufsize + 250; /* FIXME estimation */ + if (reqsize > COMMENT_OUTBUFSIZE) + { +#ifdef COMMENT_DEBUG + post("allocating %d outbuf bytes", reqsize); +#endif + if (!(outbuf = getbytes(reqsize))) + return; + } + else outbuf = buf; + outp = outbuf; + if (x->x_encoding) + sprintf(outp, "set tt [comment_entext %s {%.*s}]\n", + x->x_encoding->s_name, x->x_textbufsize, x->x_textbuf); + else + sprintf(outp, "set tt {%.*s}\n", x->x_textbufsize, x->x_textbuf); + outp += strlen(outp); + if (x->x_pixwidth) + sprintf(outp, ".x%x.c itemconfig %s -text $tt -width %d\n", + cvid, x->x_texttag, x->x_pixwidth); + else + sprintf(outp, ".x%x.c itemconfig %s -text $tt\n", cvid, x->x_texttag); + outp += strlen(outp); + if (x->x_active) + { + if (x->x_selend > x->x_selstart) + { + sprintf(outp, ".x%x.c select from %s %d\n", + cvid, x->x_texttag, x->x_selstart); + outp += strlen(outp); + sprintf(outp, ".x%x.c select to %s %d\n", + cvid, x->x_texttag, x->x_selend); + outp += strlen(outp); + sprintf(outp, ".x%x.c focus {}\n", cvid); + } + else + { + sprintf(outp, ".x%x.c select clear\n", cvid); + outp += strlen(outp); + sprintf(outp, ".x%x.c icursor %s %d\n", + cvid, x->x_texttag, x->x_selstart); + outp += strlen(outp); + sprintf(outp, ".x%x.c focus %s\n", cvid, x->x_texttag); + } + outp += strlen(outp); + } + sprintf(outp, "comment_bbox %s .x%x.c %s\n", + x->x_bindsym->s_name, cvid, x->x_texttag); + x->x_bbpending = 1; + sys_gui(outbuf); + if (outbuf != buf) freebytes(outbuf, reqsize); +} + +static void comment_validate(t_comment *x, t_glist *glist) +{ + if (!x->x_ready) + { + t_text *t = (t_text *)x; + binbuf_free(t->te_binbuf); + t->te_binbuf = x->x_binbuf; + if (x->x_textbuf) freebytes(x->x_textbuf, x->x_textbufsize); + binbuf_gettext(x->x_binbuf, &x->x_textbuf, &x->x_textbufsize); + x->x_ready = 1; +#ifdef COMMENT_DEBUG + post("validation done"); +#endif + } + if (glist) + { + if (glist != x->x_glist) + { + bug("comment_getcanvas"); + x->x_glist = glist; + } + x->x_canvas = glist_getcanvas(glist); + } +} + +static void comment_grabbedkey(void *z, t_floatarg f) +{ + /* LATER think about replacing #key binding/comment_float() with grabbing */ +} + +static void comment_dograb(t_comment *x) +{ + /* LATER investigate the grabbing feature. + Here we use it just to prevent backspace from erasing entire text. + This has to be done also when we are already active, because + after being clicked at we have lost our previous grab. */ + glist_grab(x->x_glist, (t_gobj *)x, 0, comment_grabbedkey, 0, 0); +} + +static void comment__bboxhook(t_comment *x, t_symbol *bindsym, + t_floatarg x1, t_floatarg y1, + t_floatarg x2, t_floatarg y2) +{ +#ifdef COMMENT_DEBUG + post("bbox %g %g %g %g", x1, y1, x2, y2); +#endif + x->x_x1 = x1; + x->x_y1 = y1; + x->x_x2 = x2; + x->x_y2 = y2; + x->x_bbset = 1; + x->x_bbpending = 0; +} + +static void comment__clickhook(t_comment *x, t_symbol *s, int ac, t_atom *av) +{ + int xx, yy, ndx; + if (ac == 8 && av->a_type == A_SYMBOL + && av[1].a_type == A_FLOAT && av[2].a_type == A_FLOAT + && av[3].a_type == A_FLOAT + && av[4].a_type == A_FLOAT && av[5].a_type == A_FLOAT + && av[6].a_type == A_FLOAT && av[7].a_type == A_FLOAT) + { + xx = (int)av[1].a_w.w_float; + yy = (int)av[2].a_w.w_float; + ndx = (int)av[3].a_w.w_float; + comment__bboxhook(x, av->a_w.w_symbol, + av[4].a_w.w_float, av[5].a_w.w_float, + av[6].a_w.w_float, av[7].a_w.w_float); + } + else + { + bug("comment__clickhook"); + return; + } + if (x->x_glist->gl_edit) + { + if (x->x_active) + { + if (ndx >= 0 && ndx < x->x_textbufsize) + { + /* set selection, LATER shift-click and drag */ + x->x_selstart = x->x_selend = ndx; + comment_dograb(x); + comment_update(x); + } + } + else if (xx > x->x_x2 - COMMENT_HANDLEWIDTH) + { + /* start resizing */ + char buf[COMMENT_OUTBUFSIZE], *outp = buf; + int cvid = (int)x->x_canvas; + sprintf(outp, ".x%x.c bind %s <ButtonRelease> \ + {pd [concat %s _release %s \\;]}\n", cvid, x->x_texttag, + x->x_bindsym->s_name, x->x_bindsym->s_name); + outp += strlen(outp); + sprintf(outp, ".x%x.c bind %s <Motion> \ + {pd [concat %s _motion %s %%x %%y \\;]}\n", cvid, x->x_texttag, + x->x_bindsym->s_name, x->x_bindsym->s_name); + outp += strlen(outp); + sprintf(outp, ".x%x.c create rectangle %d %d %d %d -outline blue \ + -tags {%s %s}\n", + cvid, x->x_x1, x->x_y1, x->x_x2, x->x_y2, + x->x_outlinetag, x->x_tag); + sys_gui(buf); + x->x_newx2 = x->x_x2; + x->x_dragon = 1; + } + } +} + +static void comment__releasehook(t_comment *x, t_symbol *bindsym) +{ + int cvid = (int)x->x_canvas; + sys_vgui(".x%x.c bind %s <ButtonRelease> {}\n", cvid, x->x_texttag); + sys_vgui(".x%x.c bind %s <Motion> {}\n", cvid, x->x_texttag); + sys_vgui(".x%x.c delete %s\n", cvid, x->x_outlinetag); + x->x_dragon = 0; + if (x->x_newx2 != x->x_x2) + { + x->x_pixwidth = x->x_newx2 - x->x_x1; + x->x_x2 = x->x_newx2; + comment_update(x); + } +} + +static void comment__motionhook(t_comment *x, t_symbol *bindsym, + t_floatarg xx, t_floatarg yy) +{ + int cvid = (int)x->x_canvas; + if (xx > x->x_x1 + COMMENT_MINWIDTH) + sys_vgui(".x%x.c coords %s %d %d %d %d\n", + cvid, x->x_outlinetag, + x->x_x1, x->x_y1, x->x_newx2 = xx, x->x_y2); +} + +static void commentsink__bboxhook(t_pd *x, t_symbol *bindsym, + t_floatarg x1, t_floatarg y1, + t_floatarg x2, t_floatarg y2) +{ + if (bindsym->s_thing == x) /* is the comment gone? */ + { + pd_unbind(x, bindsym); /* if so, no need for this binding anymore */ +#ifdef COMMENT_DEBUG + post("sink: %s unbound", bindsym->s_name); +#endif + } +} + +static void commentsink_anything(t_pd *x, t_symbol *s, int ac, t_atom *av) +{ + /* nop */ +} + +static void comment_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_comment *x = (t_comment *)z; + if (!glist->gl_havewindow) + { + /* LATER revisit gop behaviour. Currently text_shouldvis() returns + true if we are on parent. Here we return a null rectangle, + so that any true ui object is accessible, even if it happens + to be covered by a comment. */ + *xp1 = *yp1 = *xp2 = *yp2 = 0; + return; + } + if (x->x_bbset) + { + /* LATER think about margins */ + *xp1 = x->x_x1; + *yp1 = x->x_y1; + *xp2 = x->x_x2; + *yp2 = x->x_y2; + } + else + { + int width, height; + float x1, y1, x2, y2; + comment_validate(x, glist); + if ((width = x->x_pixwidth) < 1) + /* FIXME estimation */ + width = x->x_fontsize * x->x_textbufsize; + width += COMMENT_LMARGIN + COMMENT_RMARGIN; + /* FIXME estimation */ + height = x->x_fontsize + COMMENT_TMARGIN + COMMENT_BMARGIN; + x1 = text_xpix((t_text *)x, glist); + y1 = text_ypix((t_text *)x, glist) + 1; /* LATER revisit */ + x2 = x1 + width; + y2 = y1 + height - 2; /* LATER revisit */ +#ifdef COMMENT_DEBUG + post("estimated rectangle: %g %g %g %g", x1, y1, x2, y2); +#endif + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; + } +} + +static void comment_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_comment *x = (t_comment *)z; + if (!x->x_active && !x->x_dragon) /* LATER rethink */ + { + t_text *t = (t_text *)z; + comment_validate(x, glist); + t->te_xpix += dx; + t->te_ypix += dy; + if (x->x_bbset) + { + x->x_x1 += dx; + x->x_y1 += dy; + x->x_x2 += dx; + x->x_y2 += dy; + } + if (glist_isvisible(glist)) + sys_vgui(".x%x.c move %s %d %d\n", x->x_canvas, x->x_tag, dx, dy); + } +} + +static void comment_activate(t_gobj *z, t_glist *glist, int state) +{ + t_comment *x = (t_comment *)z; + comment_validate(x, glist); + if (state) + { + comment_dograb(x); + if (x->x_active) + return; + sys_vgui(".x%x.c focus %s\n", x->x_canvas, x->x_texttag); + x->x_selstart = 0; + x->x_selend = x->x_textbufsize; + x->x_active = 1; + pd_bind((t_pd *)x, gensym("#key")); + pd_bind((t_pd *)x, gensym("#keyname")); + } + else + { + if (!x->x_active) + return; + pd_unbind((t_pd *)x, gensym("#key")); + pd_unbind((t_pd *)x, gensym("#keyname")); + sys_vgui("selection clear .x%x.c\n", x->x_canvas); + sys_vgui(".x%x.c focus {}\n", x->x_canvas); + x->x_active = 0; + } + comment_update(x); +} + +static void comment_select(t_gobj *z, t_glist *glist, int state) +{ + t_comment *x = (t_comment *)z; + comment_validate(x, glist); + if (!state && x->x_active) comment_activate(z, glist, 0); + sys_vgui(".x%x.c itemconfigure %s -fill %s\n", x->x_canvas, + x->x_texttag, (state ? "blue" : x->x_color)); + /* A regular rtext should now set 'canvas_editing' variable to its canvas, + but we do not do that, because we get the keys through a global binding + to "#key" (and because 'canvas_editing' is not exported). */ +} + +static void comment_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_comment *x = (t_comment *)z; + t_text *t = (t_text *)z; + comment_validate(x, glist); + if (vis) + { + /* We do not need no rtext -- we are never 'textedfor' (thus + avoiding rtext calls). Creating an rtext has no other purpose + than complying to a Pd's assumption about every visible object + having an rtext (thus preventing canvas_doclick() from sending + garbage warnings). LATER revisit. */ +#ifndef PD_MINOR_VERSION + rtext_new(glist, t, glist->gl_editor->e_rtext, 0); +#endif + if (glist->gl_havewindow) + comment_draw(x); + } + else + { +#ifndef PD_MINOR_VERSION + t_rtext *rt = glist_findrtext(glist, t); + if (rt) rtext_free(rt); +#endif + /* FIXME should we test for having a window? */ +#ifdef COMMENT_DEBUG + post("deleting..."); +#endif + sys_vgui(".x%x.c delete %s\n", x->x_canvas, x->x_tag); + } +} + +static void comment_save(t_gobj *z, t_binbuf *b) +{ + t_comment *x = (t_comment *)z; + t_text *t = (t_text *)x; + comment_validate(x, 0); + binbuf_addv(b, "ssiisiissiiii", gensym("#X"), gensym("obj"), + (int)t->te_xpix, (int)t->te_ypix, + gensym("comment"), + x->x_pixwidth, x->x_fontsize, x->x_fontfamily, + (x->x_encoding ? x->x_encoding : gensym("?")), + x->x_fontprops, + (int)x->x_red, (int)x->x_green, (int)x->x_blue); + binbuf_addbinbuf(b, t->te_binbuf); + binbuf_addv(b, ";"); +} + +static t_widgetbehavior comment_widgetbehavior = +{ + comment_getrect, + comment_displace, + comment_select, + comment_activate, + 0, + comment_vis, + 0, + comment_save, + 0, +}; + +/* this fires if a transform request was sent to a symbol we are bound to */ +static void comment_transtick(t_comment *x) +{ + glist_delete(x->x_glist, (t_gobj *)x); +} + +/* what follows is basically the original code of rtext_key() */ + +static void comment_float(t_comment *x, t_float f) +{ + if (x->x_active) + { + int keynum = (int)f; + if (keynum) + { + int i, newsize, ndel; + char *s1, *s2; + int n = keynum; + if (n == '\r') n = '\n'; + if (n == '\b') + { + if ((!x->x_selstart) && (x->x_selend == x->x_textbufsize)) + { + /* LATER delete the box... this causes reentrancy + problems now. */ + /* glist_delete(x->x_glist, &x->x_text->te_g); */ + return; + } + else if (x->x_selstart && (x->x_selstart == x->x_selend)) + x->x_selstart--; + } + ndel = x->x_selend - x->x_selstart; + for (i = x->x_selend; i < x->x_textbufsize; i++) + x->x_textbuf[i- ndel] = x->x_textbuf[i]; + newsize = x->x_textbufsize - ndel; + x->x_textbuf = resizebytes(x->x_textbuf, x->x_textbufsize, newsize); + x->x_textbufsize = newsize; + + if (n == '\n' || !iscntrl(n)) + { +#ifdef COMMENT_DEBUG + post("%d accepted", n); +#endif + newsize = x->x_textbufsize+1; + x->x_textbuf = resizebytes(x->x_textbuf, + x->x_textbufsize, newsize); + for (i = x->x_textbufsize; i > x->x_selstart; i--) + x->x_textbuf[i] = x->x_textbuf[i-1]; + x->x_textbuf[x->x_selstart] = n; + x->x_textbufsize = newsize; + x->x_selstart = x->x_selstart + 1; + } +#ifdef COMMENT_DEBUG + else post("%d rejected", n); +#endif + x->x_selend = x->x_selstart; + x->x_glist->gl_editor->e_textdirty = 1; + binbuf_text(x->x_binbuf, x->x_textbuf, x->x_textbufsize); + comment_update(x); + } + } + else bug("comment_float"); +} + +static void comment_list(t_comment *x, t_symbol *s, int ac, t_atom *av) +{ + if (!x->x_active) + bug("comment_list"); + else if (ac > 1 && av->a_type == A_FLOAT && (int)av->a_w.w_float + && av[1].a_type == A_SYMBOL) + { + t_symbol *keysym = av[1].a_w.w_symbol; + if (!strcmp(keysym->s_name, "Right")) + { + if (x->x_selend == x->x_selstart && + x->x_selstart < x->x_textbufsize) + x->x_selend = x->x_selstart = x->x_selstart + 1; + else + x->x_selstart = x->x_selend; + } + else if (!strcmp(keysym->s_name, "Left")) + { + if (x->x_selend == x->x_selstart && x->x_selstart > 0) + x->x_selend = x->x_selstart = x->x_selstart - 1; + else + x->x_selend = x->x_selstart; + } + /* this should be improved... life's too short */ + else if (!strcmp(keysym->s_name, "Up")) + { + if (x->x_selstart) + x->x_selstart--; + while (x->x_selstart > 0 && x->x_textbuf[x->x_selstart] != '\n') + x->x_selstart--; + x->x_selend = x->x_selstart; + } + else if (!strcmp(keysym->s_name, "Down")) + { + while (x->x_selend < x->x_textbufsize && + x->x_textbuf[x->x_selend] != '\n') + x->x_selend++; + if (x->x_selend < x->x_textbufsize) + x->x_selend++; + x->x_selstart = x->x_selend; + } + else if (!strcmp(keysym->s_name, "F4")) + { + t_text *newt, *oldt = (t_text *)x; + t_binbuf *bb = binbuf_new(); + int ac = binbuf_getnatom(x->x_binbuf); + binbuf_addv(bb, "siissiiii", gensym("comment"), x->x_pixwidth, + x->x_fontsize, x->x_fontfamily, + (x->x_encoding ? x->x_encoding : gensym("?")), + x->x_fontprops, + (int)x->x_red, (int)x->x_green, (int)x->x_blue); + binbuf_add(bb, ac, binbuf_getvec(x->x_binbuf)); + canvas_setcurrent(x->x_glist); + newt = (t_text *)pd_new(makeshift_class); + newt->te_width = 0; + newt->te_type = T_OBJECT; + newt->te_binbuf = bb; + newt->te_xpix = oldt->te_xpix; + newt->te_ypix = oldt->te_ypix; + glist_add(x->x_glist, &newt->te_g); + glist_noselect(x->x_glist); + glist_select(x->x_glist, &newt->te_g); + gobj_activate(&newt->te_g, x->x_glist, 1); + x->x_glist->gl_editor->e_textdirty = 1; /* force evaluation */ + canvas_unsetcurrent(x->x_glist); + canvas_dirty(x->x_glist, 1); + clock_delay(x->x_transclock, 0); /* LATER rethink */ + return; + } + else if (!strcmp(keysym->s_name, "F5")) + { + t_text *t = (t_text *)x; + t_binbuf *bb = binbuf_new(); + int ac = binbuf_getnatom(x->x_binbuf); + binbuf_addv(bb, "ii", (int)t->te_xpix + 5, (int)t->te_ypix + 5); + binbuf_add(bb, ac, binbuf_getvec(x->x_binbuf)); + canvas_setcurrent(x->x_glist); + typedmess((t_pd *)x->x_glist, gensym("text"), + ac + 2, binbuf_getvec(bb)); + canvas_unsetcurrent(x->x_glist); + canvas_dirty(x->x_glist, 1); + binbuf_free(bb); + return; + } + else return; + comment_update(x); + } +} + +static void comment_free(t_comment *x) +{ + if (x->x_active) + { + bug("comment_free"); + pd_unbind((t_pd *)x, gensym("#key")); + pd_unbind((t_pd *)x, gensym("#keyname")); + } + if (x->x_transclock) clock_free(x->x_transclock); + if (x->x_bindsym) + { + pd_unbind((t_pd *)x, x->x_bindsym); + if (!x->x_bbpending) + pd_unbind(commentsink, x->x_bindsym); + } + if (x->x_binbuf && !x->x_ready) binbuf_free(x->x_binbuf); + if (x->x_textbuf) freebytes(x->x_textbuf, x->x_textbufsize); +} + +/* the arguments in the full form of a creation message are: + + width fontsize fontfamily encoding fontprops red green blue text... + + For comments typed into an object box, the text part begins with + the first atom satisfying one of the following conditions (skipped + arguments get default values): + + . having a different type than the corresponding argument of the + full form + + . being preceded with a dot atom ('.') put in place of a symbol + argument (fontfamily or encoding) + + . being the 10th atom in a box + + The question mark atom ('?') may be used to supply a default fontfamily + or an empty encoding value. +*/ + +static void *comment_new(t_symbol *s, int ac, t_atom *av) +{ + t_comment *x = (t_comment *)pd_new(comment_class); + t_text *t = (t_text *)x; + t_atom at; + char buf[32]; + t->te_type = T_TEXT; + x->x_glist = canvas_getcurrent(); + x->x_canvas = 0; + sprintf(x->x_tag, "all%x", (int)x); + sprintf(x->x_texttag, "t%x", (int)x); + sprintf(x->x_outlinetag, "h%x", (int)x); + x->x_pixwidth = 0; + x->x_fontsize = 0; + x->x_fontfamily = 0; + x->x_encoding = 0; + x->x_fontprops = 0; + x->x_red = 0; + x->x_green = 0; + x->x_blue = 0; + + if (ac && av->a_type == A_FLOAT) + { + x->x_pixwidth = (int)av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + x->x_fontsize = (int)av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == gensym(".")) + { + ac--; av++; + goto textpart; + } + else if (av->a_w.w_symbol != gensym("?")) + x->x_fontfamily = av->a_w.w_symbol; + ac--; av++; + if (ac && av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == gensym(".")) + { + ac--; av++; + goto textpart; + } + else if (av->a_w.w_symbol != gensym("?")) + x->x_encoding = av->a_w.w_symbol; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + x->x_fontprops = (int)av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + x->x_red = (unsigned char)av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + x->x_green = (unsigned char)av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + x->x_blue = (unsigned char)av->a_w.w_float; + ac--; av++; + } + } + } + } + } + } + } + } +textpart: + if (x->x_fontsize < 1) + x->x_fontsize = glist_getfont(x->x_glist); + if (!x->x_fontfamily) + x->x_fontfamily = gensym("helvetica"); + sprintf(x->x_color, "#%2.2x%2.2x%2.2x", x->x_red, x->x_green, x->x_blue); + + x->x_binbuf = binbuf_new(); + if (ac) binbuf_restore(x->x_binbuf, ac, av); + else + { + SETSYMBOL(&at, gensym("comment")); + binbuf_restore(x->x_binbuf, 1, &at); + } + x->x_textbuf = 0; + x->x_textbufsize = 0; + x->x_transclock = clock_new(x, (t_method)comment_transtick); + x->x_bbset = 0; + x->x_bbpending = 0; + sprintf(buf, "miXed%x", (int)x); + x->x_bindsym = gensym(buf); + pd_bind((t_pd *)x, x->x_bindsym); + if (!commentsink) + commentsink = pd_new(commentsink_class); + pd_bind(commentsink, x->x_bindsym); + x->x_ready = 0; + x->x_dragon = 0; + return (x); +} + +void comment_setup(void) +{ + comment_class = class_new(gensym("comment"), + (t_newmethod)comment_new, + (t_method)comment_free, + sizeof(t_comment), + CLASS_NOINLET | CLASS_PATCHABLE, + A_GIMME, 0); + class_addfloat(comment_class, comment_float); + class_addlist(comment_class, comment_list); + class_addmethod(comment_class, (t_method)comment__bboxhook, + gensym("_bbox"), + A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_addmethod(comment_class, (t_method)comment__clickhook, + gensym("_click"), A_GIMME, 0); + class_addmethod(comment_class, (t_method)comment__releasehook, + gensym("_release"), A_SYMBOL, 0); + class_addmethod(comment_class, (t_method)comment__motionhook, + gensym("_motion"), A_SYMBOL, A_FLOAT, A_FLOAT, 0); + class_setwidget(comment_class, &comment_widgetbehavior); + + makeshift_class = class_new(gensym("text"), 0, 0, + sizeof(t_text), + CLASS_NOINLET | CLASS_PATCHABLE, 0); + + commentsink_class = class_new(gensym("_commentsink"), 0, 0, + sizeof(t_pd), CLASS_PD, 0); + class_addanything(commentsink_class, commentsink_anything); + class_addmethod(commentsink_class, (t_method)commentsink__bboxhook, + gensym("_bbox"), + A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + + sys_gui("proc comment_bbox {target cvname tag} {\n\ + pd $target _bbox $target [$cvname bbox $tag]\\;}\n"); + + /* LATER think about window vs canvas coords */ + sys_gui("proc comment_click {target cvname x y tag} {\n\ + pd $target _click $target [$cvname canvasx $x] [$cvname canvasy $y]\ + [$cvname index $tag @$x,$y] [$cvname bbox $tag]\\;}\n"); + + sys_gui("proc comment_entext {enc tt} {\n\ + set rr [catch {encoding convertfrom $enc $tt} tt1]\n\ + if {$rr == 0} {concat $tt1} else {\n\ + puts stderr [concat tcl/tk error: $tt1]\n\ + concat $tt}}\n"); +} diff --git a/cyclone/hammer/cosh.c b/cyclone/hammer/cosh.c new file mode 100644 index 0000000..77d1567 --- /dev/null +++ b/cyclone/hammer/cosh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define coshf cosh +#endif + +typedef struct _cosh +{ + t_object x_ob; + float x_value; +} t_cosh; + +static t_class *cosh_class; + +static void cosh_bang(t_cosh *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void cosh_float(t_cosh *x, t_float f) +{ + /* CHECKME large values */ + outlet_float(((t_object *)x)->ob_outlet, x->x_value = coshf(f)); +} + +static void *cosh_new(t_floatarg f) +{ + t_cosh *x = (t_cosh *)pd_new(cosh_class); + /* CHECKME large values */ + x->x_value = coshf(f); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void cosh_setup(void) +{ + cosh_class = class_new(gensym("cosh"), + (t_newmethod)cosh_new, 0, + sizeof(t_cosh), 0, A_DEFFLOAT, 0); + class_addbang(cosh_class, cosh_bang); + class_addfloat(cosh_class, cosh_float); +} diff --git a/cyclone/hammer/counter.c b/cyclone/hammer/counter.c new file mode 100644 index 0000000..3117e6c --- /dev/null +++ b/cyclone/hammer/counter.c @@ -0,0 +1,399 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is an entirely rewritten version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +/* Beware -- the max reference manual page for the counter object + reflects mostly opcode max features. Apparently counter works + differently in cycling max (e.g. inlets 3 and 4). But I am sick + of checking -- I will not bother, until there is some feedback. */ + +#include "m_pd.h" + +#define COUNTER_UP 0 +#define COUNTER_DOWN 1 +#define COUNTER_UPDOWN 2 +#define COUNTER_DEFMAX 0x7fffffff /* CHECKED (man says otherwise) */ + +typedef struct _counter +{ + t_object x_ob; + int x_count; + int x_maxcount; + int x_dir; + int x_inc; + int x_min; + int x_max; + int x_carrybang; + int x_minhitflag; + int x_maxhitflag; + t_pd *x_proxies[4]; + t_outlet *x_out2; + t_outlet *x_out3; + t_outlet *x_out4; +} t_counter; + +typedef struct _counter_proxy +{ + t_object p_ob; + t_counter *p_master; + void (*p_bangmethod)(t_counter *x); + void (*p_floatmethod)(t_counter *x, t_float f); +} t_counter_proxy; + +static t_class *counter_class; +static t_class *counter_proxy_class; + +static void counter_up(t_counter *x) +{ + x->x_dir = COUNTER_UP; + x->x_inc = 1; +} + +static void counter_down(t_counter *x) +{ + /* CHECKED: no explicit minimum needed */ + x->x_dir = COUNTER_DOWN; + x->x_inc = -1; +} + +static void counter_updown(t_counter *x) +{ + /* CHECKED: neither explicit maximum, nor minimum needed */ + x->x_dir = COUNTER_UPDOWN; + /* CHECKED: x->x_inc unchanged (continuation) */ +} + +static void counter_dir(t_counter *x, t_floatarg f) +{ + switch ((int)f) + { + case COUNTER_UP: + counter_up(x); + break; + case COUNTER_DOWN: + counter_down(x); + break; + case COUNTER_UPDOWN: + counter_updown(x); + break; + default: + counter_up(x); /* CHECKED: invalid == default */ + /* CHECKED: no warning */ + } +} + +static void counter_dobang(t_counter *x, int notjam) +{ + int offmin = 0, offmax = 0, onmin = 0, onmax = 0; + /* CHECKED: carry-off is not sent if min >= max */ + /* LATER rethink (this is a hack) */ + if (x->x_min < x->x_max) + offmin = x->x_minhitflag, offmax = x->x_maxhitflag; + x->x_minhitflag = x->x_maxhitflag = 0; + + if (x->x_count < x->x_min) + { + if (x->x_inc == 1) + { + /* min has changed, which should imply x->x_count == x->x_min */ + bug("counter_dobang (count < min)"); + } + else if (x->x_dir == COUNTER_UPDOWN) + { + x->x_inc = 1; + if ((x->x_count = x->x_min + 1) > x->x_max) x->x_count = x->x_min; + } + else if ((x->x_count = x->x_max) < x->x_min) x->x_count = x->x_min; + } + else if (x->x_count > x->x_max) + { + if (x->x_inc == -1) + { + /* CHECKED: ignored */ + } + else if (x->x_dir == COUNTER_UPDOWN) + { + x->x_inc = -1; + if ((x->x_count = x->x_max - 1) < x->x_min) x->x_count = x->x_min; + } + else x->x_count = x->x_min; + } + + if (x->x_count == x->x_min && x->x_inc == -1) + { + /* CHECKED: 'jam' inhibits middle outlets (unless carry-off) + carry-on is never sent if max < min, but sent if max == min */ + if (notjam + && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */ + onmin = 1; + } + else if (x->x_count == x->x_max && x->x_inc == 1) + { + /* CHECKED: this counter is never reset (and goes up to INT_MAX) + -- neither after dir change, nor after max change */ + x->x_maxcount++; /* CHECKED: 'jam' does the increment */ + outlet_float(x->x_out4, x->x_maxcount); + /* CHECKED: 'jam' inhibits middle outlets (unless carry-off) + carry-on is never sent if max < min, but sent if max == min */ + if (notjam + && x->x_min <= x->x_max) /* LATER rethink (this is a hack) */ + onmax = 1; + } + + /* CHECKED: outlets deliver in right-to-left order */ + if (onmax) + { + if (x->x_carrybang) outlet_bang(x->x_out3); + else + { + outlet_float(x->x_out3, 1); + x->x_maxhitflag = 1; + } + } + else if (offmax) outlet_float(x->x_out3, 0); + else if (onmin) + { + if (x->x_carrybang) outlet_bang(x->x_out2); + else + { + outlet_float(x->x_out2, 1); + x->x_minhitflag = 1; + } + } + else if (offmin) outlet_float(x->x_out2, 0); + + outlet_float(((t_object *)x)->ob_outlet, x->x_count); +} + +static void counter_bang(t_counter *x) +{ + x->x_count += x->x_inc; + counter_dobang(x, 1); +} + +static void counter_float(t_counter *x, t_float dummy) +{ + counter_bang(x); +} + +/* CHECKED: out-of-range values are ignored */ +/* CHECKED: 'down, set 3, up, bang' gives 5 */ +static void counter_set(t_counter *x, t_floatarg f) +{ + int i = (int)f; + if (i >= x->x_min && i <= x->x_max) + x->x_count = i - x->x_inc; +} + +/* CHECKED: out-of-range values are ignored */ +static void counter_jam(t_counter *x, t_floatarg f) +{ + int i = (int)f; + if (i >= x->x_min && i <= x->x_max) + { + x->x_count = i; + counter_dobang(x, 0); + } +} + +/* CHECKED: sends max carry on/off in any mode */ +static void counter_inc(t_counter *x) +{ + int tempdir = x->x_dir; + int tempinc = x->x_inc; + counter_up(x); + counter_bang(x); + x->x_dir = tempdir; + x->x_inc = tempinc; +} + +/* CHECKED: sends min carry on/off in any mode */ +static void counter_dec(t_counter *x) +{ + int tempdir = x->x_dir; + int tempinc = x->x_inc; + counter_down(x); + counter_bang(x); + x->x_dir = tempdir; + x->x_inc = tempinc; +} + +/* CHECKED: min can be set over max */ +static void counter_min(t_counter *x, t_floatarg f) +{ + /* CHECKED: min change always sets count to min and bangs */ + /* do not use counter_jam() here -- avoid range checking */ + x->x_count = x->x_min = (int)f; + counter_dobang(x, 0); +} + +/* CHECKED: max can be set below min */ +static void counter_max(t_counter *x, t_floatarg f) +{ + x->x_max = (int)f; +} + +static void counter_carrybang(t_counter *x) +{ + x->x_carrybang = 1; +} + +static void counter_carryint(t_counter *x) +{ + x->x_carrybang = 0; +} + +/* CHECKED: up/down switch */ +static void counter_bang1(t_counter *x) +{ + if (x->x_dir == COUNTER_UP) + counter_down(x); + else if (x->x_dir == COUNTER_DOWN) + counter_up(x); + else + x->x_inc = -x->x_inc; /* CHECKED */ +} + +/* CHECKED */ +static void counter_bang2(t_counter *x) +{ + counter_set(x, x->x_min); +} + +/* CHECKED: out-of-range values are accepted (LATER rethink) */ +/* CHECKED: no resetting of min, nor of max (contrary to the man) */ +/* CHECKED: 'down, float2 3, up, bang' gives 3 (LATER rethink) */ +static void counter_float2(t_counter *x, t_floatarg f) +{ + counter_set(x, f); /* FIXME */ +} + +/* CHECKED */ +static void counter_bang3(t_counter *x) +{ + counter_jam(x, x->x_min); +} + +/* CHECKED: out-of-range values are accepted (LATER rethink) */ +/* CHECKED: no resetting of min, nor of max (contrary to the man) */ +static void counter_float3(t_counter *x, t_floatarg f) +{ + counter_jam(x, f); /* FIXME */ +} + +/* CHECKED */ +static void counter_bang4(t_counter *x) +{ + counter_set(x, x->x_max); +} + +static void counter_proxy_bang(t_counter_proxy *x) +{ + x->p_bangmethod(x->p_master); +} + +static void counter_proxy_float(t_counter_proxy *x, t_float f) +{ + x->p_floatmethod(x->p_master, f); +} + +static void counter_free(t_counter *x) +{ + int i; + for (i = 0; i < 4; i++) + if (x->x_proxies[i]) pd_free(x->x_proxies[i]); +} + +static void *counter_new(t_floatarg f1, t_floatarg f2, t_floatarg f3) +{ + t_counter *x = (t_counter *)pd_new(counter_class); + t_counter_proxy **pp = (t_counter_proxy **)x->x_proxies; + int i1 = (int)f1; + int i2 = (int)f2; + int i3 = (int)f3; + int i; + static int warned = 0; + if (!warned) + { + post("warning: counter is not fully compatible, \ +please report differences"); + warned = 1; + } + x->x_dir = COUNTER_UP; + x->x_inc = 1; /* previous value required by counter_dir() */ + x->x_min = 0; + x->x_max = COUNTER_DEFMAX; + if (i3) x->x_dir = i1, x->x_min = i2, x->x_max = i3; + else if (i2) x->x_min = i1, x->x_max = i2; + else if (i1) x->x_max = i1; + x->x_carrybang = 0; /* CHECKED */ + x->x_minhitflag = x->x_maxhitflag = 0; + x->x_maxcount = 0; + counter_dir(x, x->x_dir); + /* CHECKED: [counter 1 <min> <max>] starts from <max> */ + x->x_count = (x->x_dir == COUNTER_DOWN ? x->x_max : x->x_min); + for (i = 0; i < 4; i++) + { + x->x_proxies[i] = pd_new(counter_proxy_class); + ((t_counter_proxy *)x->x_proxies[i])->p_master = x; + inlet_new((t_object *)x, x->x_proxies[i], 0, 0); + } + (*pp)->p_bangmethod = counter_bang1; + (*pp++)->p_floatmethod = counter_dir; /* CHECKED: same as dir */ + (*pp)->p_bangmethod = counter_bang2; + (*pp++)->p_floatmethod = counter_float2; + (*pp)->p_bangmethod = counter_bang3; + (*pp++)->p_floatmethod = counter_float3; + (*pp)->p_bangmethod = counter_bang4; + (*pp++)->p_floatmethod = counter_max; /* CHECKED: same as max */ + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_anything); /* float/bang */ + x->x_out3 = outlet_new((t_object *)x, &s_anything); /* float/bang */ + x->x_out4 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void counter_setup(void) +{ + counter_class = class_new(gensym("counter"), + (t_newmethod)counter_new, + (t_method)counter_free, + sizeof(t_counter), 0, + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(counter_class, counter_bang); + class_addfloat(counter_class, counter_float); + class_addmethod(counter_class, (t_method)counter_bang, + gensym("next"), 0); + class_addmethod(counter_class, (t_method)counter_set, + gensym("set"), A_FLOAT, 0); + class_addmethod(counter_class, (t_method)counter_set, + gensym("goto"), A_FLOAT, 0); + class_addmethod(counter_class, (t_method)counter_jam, + gensym("jam"), A_FLOAT, 0); + class_addmethod(counter_class, (t_method)counter_up, + gensym("up"), 0); + class_addmethod(counter_class, (t_method)counter_down, + gensym("down"), 0); + class_addmethod(counter_class, (t_method)counter_updown, + gensym("updown"), 0); + class_addmethod(counter_class, (t_method)counter_inc, + gensym("inc"), 0); + class_addmethod(counter_class, (t_method)counter_dec, + gensym("dec"), 0); + class_addmethod(counter_class, (t_method)counter_min, + gensym("min"), A_FLOAT, 0); + class_addmethod(counter_class, (t_method)counter_max, + gensym("max"), A_FLOAT, 0); + class_addmethod(counter_class, (t_method)counter_carrybang, + gensym("carrybang"), 0); + class_addmethod(counter_class, (t_method)counter_carryint, + gensym("carryint"), 0); + counter_proxy_class = class_new(gensym("_counter_proxy"), 0, 0, + sizeof(t_counter_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(counter_proxy_class, counter_proxy_bang); + class_addfloat(counter_proxy_class, counter_proxy_float); +} diff --git a/cyclone/hammer/cycle.c b/cyclone/hammer/cycle.c new file mode 100644 index 0000000..faffc01 --- /dev/null +++ b/cyclone/hammer/cycle.c @@ -0,0 +1,153 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a modified version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +#include "m_pd.h" +#include "common/loud.h" + +//#define CYCLE_USEEVENTNO + +#define CYCLE_MINOUTS 1 +#define CYCLE_MAXOUTS 100 /* CHECKED */ +#define CYCLE_DEFOUTS 1 + +typedef struct _cycle +{ + t_object x_ob; + int x_eventmode; +#ifdef CYCLE_USEEVENTNO + int x_lastevent; +#else + double x_lastevent; +#endif + int x_index; + int x_nouts; + t_outlet **x_outs; +} t_cycle; + +static t_class *cycle_class; + +static int cycle_isnextevent(t_cycle *x) +{ +#ifdef CYCLE_USEEVENTNO + int nextevent = sys_geteventno(); +#else + double nextevent = clock_getlogicaltime(); +#endif + if (x->x_lastevent == nextevent) + return (0); + else + { + x->x_lastevent = nextevent; + return (1); + } +} + +static void cycle_bang(t_cycle *x) +{ + /* CHECKED: bangs ignored (but message 'bang' is an error -- why?) */ +} + +static void cycle_float(t_cycle *x, t_float f) +{ + if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts) + x->x_index = 0; + outlet_float(x->x_outs[x->x_index++], f); +} + +static void cycle_symbol(t_cycle *x, t_symbol *s) +{ + if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts) + x->x_index = 0; + outlet_symbol(x->x_outs[x->x_index++], s); +} + +/* LATER gpointer */ + +static void cycle_list(t_cycle *x, t_symbol *s, int ac, t_atom *av) +{ + if ((x->x_eventmode && cycle_isnextevent(x)) || x->x_index >= x->x_nouts) + x->x_index = 0; + while (ac--) + { + if (av->a_type == A_FLOAT) + outlet_float(x->x_outs[x->x_index], av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(x->x_outs[x->x_index], av->a_w.w_symbol); + av++; + if (++(x->x_index) >= x->x_nouts) x->x_index = 0; + } +} + +static void cycle_anything(t_cycle *x, t_symbol *s, int ac, t_atom *av) +{ + if (s && s != &s_) cycle_symbol(x, s); /* CHECKED */ + cycle_list(x, 0, ac, av); +} + +static void cycle_set(t_cycle *x, t_floatarg f) +{ + int i = (int)f; + if (i >= 0 && i < x->x_nouts) x->x_index = i; +} + +static void cycle_thresh(t_cycle *x, t_floatarg f) +{ + if (x->x_eventmode = (f != 0)) +#ifdef CYCLE_USEEVENTNO + x->x_lastevent = sys_geteventno(); +#else + x->x_lastevent = clock_getlogicaltime(); +#endif +} + +static void cycle_free(t_cycle *x) +{ + if (x->x_outs) + freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); +} + +static void *cycle_new(t_floatarg f1, t_floatarg f2) +{ + t_cycle *x; + int i, nouts = (int)f1; + t_outlet **outs; + if (nouts < CYCLE_MINOUTS) + nouts = CYCLE_DEFOUTS; + if (nouts > CYCLE_MAXOUTS) + { + loud_incompatible_max(cycle_class, CYCLE_MAXOUTS, "outlets"); + /* CHECKED: max clips with an error: + ``perhaps you were trying to make an oscillator?'' */ + } + if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) + return (0); + x = (t_cycle *)pd_new(cycle_class); + x->x_nouts = nouts; + x->x_outs = outs; + x->x_index = 0; + for (i = 0; i < nouts; i++) + x->x_outs[i] = outlet_new((t_object *)x, &s_anything); + cycle_thresh(x, f2); + return (x); +} + +void cycle_setup(void) +{ + cycle_class = class_new(gensym("cycle"), + (t_newmethod)cycle_new, + (t_method)cycle_free, + sizeof(t_cycle), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(cycle_class, cycle_bang); + class_addfloat(cycle_class, cycle_float); + class_addsymbol(cycle_class, cycle_symbol); + class_addlist(cycle_class, cycle_list); + class_addanything(cycle_class, cycle_anything); + class_addmethod(cycle_class, (t_method)cycle_set, + gensym("set"), A_FLOAT, 0); /* CHECKED: arg required */ + class_addmethod(cycle_class, (t_method)cycle_thresh, + gensym("thresh"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/decide.c b/cyclone/hammer/decide.c new file mode 100644 index 0000000..a612fbf --- /dev/null +++ b/cyclone/hammer/decide.c @@ -0,0 +1,75 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +typedef struct _decide +{ + t_object x_ob; + unsigned int x_seed; +} t_decide; + +static t_class *decide_class; + +/* the random bit algo is taken from NR (method II in 7.4) -- CHECKED */ +#define RBIT1 1 +#define RBIT2 2 +#define RBIT5 16 +#define RBIT18 131072 +#define RBIT_MASK (RBIT1 + RBIT2 + RBIT5) + +static void decide_bang(t_decide *x) +{ + if (x->x_seed & RBIT18) + { + x->x_seed = ((x->x_seed ^ RBIT_MASK) << 1) | RBIT1; + outlet_float(((t_object *)x)->ob_outlet, 1); + } + else + { + x->x_seed <<= 1; + outlet_float(((t_object *)x)->ob_outlet, 0); + } +} + +static void decide_float(t_decide *x, t_float f) +{ + /* CHECKED: float loudly rejected, int (any value) same as bang */ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) + decide_bang(x); +} + +static void decide_ft1(t_decide *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED */ + if (i) /* CHECKED: negative numbers are accepted */ + x->x_seed = i; + else + x->x_seed = 123456789; /* FIXME */ +} + +static void *decide_new(t_floatarg f) +{ + t_decide *x = (t_decide *)pd_new(decide_class); + x->x_seed = 123456789; /* FIXME */ + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void decide_setup(void) +{ + decide_class = class_new(gensym("decide"), + (t_newmethod)decide_new, 0, + sizeof(t_decide), 0, + A_DEFFLOAT, 0); + class_addbang(decide_class, decide_bang); + class_addfloat(decide_class, decide_float); + class_addmethod(decide_class, (t_method)decide_ft1, + gensym("ft1"), A_FLOAT, 0); + /* CHECKED list is auto-unfolded */ + /* CHECKED doesn't understand "seed" */ +} diff --git a/cyclone/hammer/drunk.c b/cyclone/hammer/drunk.c new file mode 100644 index 0000000..e08800d --- /dev/null +++ b/cyclone/hammer/drunk.c @@ -0,0 +1,140 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The first version of this code was written by Nicola Bernardini. + It was entirely reimplemented in the hope of adapting it to the + cyclone's guidelines. */ + +#include "m_pd.h" +#include "common/rand.h" + +#define DRUNK_DEFMAXVALUE 128 +#define DRUNK_DEFMAXSTEP 2 + +typedef struct _drunk +{ + t_object x_ob; + int x_value; + int x_maxvalue; + int x_maxstep; + int x_minstep; + unsigned int x_seed; + unsigned int x_bitseed; +} t_drunk; + +static t_class *drunk_class; + +static void drunk_set(t_drunk *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED float silently truncated */ + if (i > x->x_maxvalue) + x->x_value = x->x_maxvalue; /* CHECKED */ + else if (i < 0) + x->x_value = 0; /* CHECKED */ + else x->x_value = i; +} + +/* CHECKED: this is a superposition of two rngs -- the random bit generator, + and the random integer generator, which is the same (CHECKED) as the one + used in the 'random' class (quite lame: period 35730773, nonuniform for + large ranges, so I would rather not RE it...) */ +#define RBIT1 1 +#define RBIT2 2 +#define RBIT5 16 +#define RBIT18 131072 +#define RBIT_MASK (RBIT1 + RBIT2 + RBIT5) + +static void drunk_bang(t_drunk *x) +{ + int rnd = rand_int(&x->x_seed, x->x_maxstep) + x->x_minstep; + int val; + if (x->x_bitseed & RBIT18) + { + x->x_bitseed = ((x->x_bitseed ^ RBIT_MASK) << 1) | RBIT1; + if ((val = x->x_value + rnd) > x->x_maxvalue) + val = x->x_value - rnd; /* CHECKED */ + if (val < 0) + val = 0; /* CHECKED (needed for maxstep > maxvalue) */ + } + else + { + x->x_bitseed <<= 1; + if ((val = x->x_value - rnd) < 0) + val = x->x_value + rnd; /* CHECKED */ + if (val > x->x_maxvalue) + val = x->x_maxvalue; /* CHECKED (needed for maxstep > maxvalue) */ + } + outlet_float(((t_object *)x)->ob_outlet, x->x_value = val); +} + +static void drunk_float(t_drunk *x, t_float f) +{ + drunk_set(x, f); + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void drunk_ft1(t_drunk *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED float silently truncated */ + x->x_maxvalue = (i < 0 ? 1 : i); /* CHECKED zero allowed */ + /* CHECKED maxstep not updated */ +} + +static void drunk_ft2(t_drunk *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED float silently truncated */ + if (i < 0) + { + x->x_minstep = 1; + i = -i; + } + else x->x_minstep = 0; + /* CHECKED maxstep not clipped to the maxvalue */ + x->x_maxstep = (x->x_minstep ? i - 1 : i); /* CHECKED zero allowed */ +} + +/* apparently, bitseed cannot be controlled, but LATER recheck */ +static void drunk_seed(t_drunk *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED */ + if (i < 0) + i = 1; /* CHECKED */ + rand_seed(&x->x_seed, (unsigned int)i); +} + +static void *drunk_new(t_floatarg f1, t_floatarg f2) +{ + t_drunk *x = (t_drunk *)pd_new(drunk_class); + x->x_maxvalue = ((int)f1 > 0 ? (int)f1 : 128); /* CHECKED */ + x->x_maxstep = 2; + x->x_minstep = 0; + if ((int)f2) /* CHECKED */ + drunk_ft2(x, f2); + x->x_value = x->x_maxvalue / 2; /* CHECKED */ + rand_seed(&x->x_seed, 0); /* CHECKED third arg silently ignored */ + x->x_bitseed = 123456789; /* FIXME */ + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void drunk_setup(void) +{ + drunk_class = class_new(gensym("drunk"), + (t_newmethod)drunk_new, 0, + sizeof(t_drunk), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(drunk_class, drunk_bang); + class_addfloat(drunk_class, drunk_float); + class_addmethod(drunk_class, (t_method)drunk_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(drunk_class, (t_method)drunk_ft2, + gensym("ft2"), A_FLOAT, 0); + /* CHECKED list is auto-unfolded */ + class_addmethod(drunk_class, (t_method)drunk_seed, + gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */ + class_addmethod(drunk_class, (t_method)drunk_set, + gensym("set"), A_FLOAT, 0); /* CHECKED arg obligatory */ +} diff --git a/cyclone/hammer/flush.c b/cyclone/hammer/flush.c new file mode 100644 index 0000000..751fc24 --- /dev/null +++ b/cyclone/hammer/flush.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" + +#define FLUSH_NPITCHES 128 + +typedef struct _flush +{ + t_object x_ob; + t_float x_velocity; + unsigned char x_pitches[FLUSH_NPITCHES]; /* CHECKED */ + t_outlet *x_voutlet; +} t_flush; + +static t_class *flush_class; + +static void flush_float(t_flush *x, t_float f) +{ + int pitch = (int)f; + if (pitch >= 0 && pitch < FLUSH_NPITCHES) + { + outlet_float(x->x_voutlet, x->x_velocity); + outlet_float(((t_object *)x)->ob_outlet, pitch); + if (x->x_velocity != 0) + { + x->x_pitches[pitch]++; /* CHECKED (lame) */ + } + else if (x->x_pitches[pitch]) + { + x->x_pitches[pitch]--; /* CHECKED (lame) */ + } + } +} + +static void flush_bang(t_flush *x) +{ + int i; + unsigned char *pp; + for (i = 0, pp = x->x_pitches; i < FLUSH_NPITCHES; i++, pp++) + { + while (*pp) + { + outlet_float(x->x_voutlet, 0); + outlet_float(((t_object *)x)->ob_outlet, i); + (*pp)--; + } + } +} + +static void flush_clear(t_flush *x) +{ + memset(x->x_pitches, 0, sizeof(x->x_pitches)); +} + +static void *flush_new(void) +{ + t_flush *x = (t_flush *)pd_new(flush_class); + x->x_velocity = 0; + flush_clear(x); + floatinlet_new((t_object *)x, &x->x_velocity); + outlet_new((t_object *)x, &s_float); + x->x_voutlet = outlet_new((t_object *)x, &s_float); + return (x); +} + +void flush_setup(void) +{ + flush_class = class_new(gensym("flush"), + (t_newmethod)flush_new, + 0, /* CHECKED: no flushout */ + sizeof(t_flush), 0, 0); + class_addfloat(flush_class, flush_float); + class_addbang(flush_class, flush_bang); + class_addmethod(flush_class, (t_method)flush_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/forward.c b/cyclone/hammer/forward.c new file mode 100644 index 0000000..995e765 --- /dev/null +++ b/cyclone/hammer/forward.c @@ -0,0 +1,71 @@ +/* Copyright (c) 1997-2002 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _forward +{ + t_object x_ob; + t_symbol *x_sym; +} t_forward; + +static t_class *forward_class; + +static void forward_bang(t_forward *x) +{ + if (x->x_sym->s_thing) pd_bang(x->x_sym->s_thing); +} + +static void forward_float(t_forward *x, t_float f) +{ + if (x->x_sym->s_thing) pd_float(x->x_sym->s_thing, f); +} + +static void forward_symbol(t_forward *x, t_symbol *s) +{ + if (x->x_sym->s_thing) pd_symbol(x->x_sym->s_thing, s); +} + +static void forward_pointer(t_forward *x, t_gpointer *gp) +{ + if (x->x_sym->s_thing) pd_pointer(x->x_sym->s_thing, gp); +} + +static void forward_list(t_forward *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_sym->s_thing) pd_list(x->x_sym->s_thing, s, ac, av); +} + +static void forward_anything(t_forward *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_sym->s_thing) typedmess(x->x_sym->s_thing, s, ac, av); +} + +static void forward_send(t_forward *x, t_symbol *s) +{ + /* CHECKED: 'send' without arguments erases destination */ + if (s) x->x_sym = s; +} + +static void *forward_new(t_symbol *s) +{ + t_forward *x = (t_forward *)pd_new(forward_class); + x->x_sym = s; + return (x); +} + +void forward_setup(void) +{ + forward_class = class_new(gensym("forward"), + (t_newmethod)forward_new, 0, + sizeof(t_forward), 0, A_DEFSYM, 0); + class_addbang(forward_class, forward_bang); + class_addfloat(forward_class, forward_float); + class_addsymbol(forward_class, forward_symbol); + class_addpointer(forward_class, forward_pointer); + class_addlist(forward_class, forward_list); + class_addanything(forward_class, forward_anything); + class_addmethod(forward_class, (t_method)forward_send, + gensym("send"), A_DEFSYM, 0); +} diff --git a/cyclone/hammer/fromsymbol.c b/cyclone/hammer/fromsymbol.c new file mode 100644 index 0000000..3d508e9 --- /dev/null +++ b/cyclone/hammer/fromsymbol.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" + +typedef struct _fromsymbol +{ + t_object x_ob; +} t_fromsymbol; + +static t_class *fromsymbol_class; + +static void fromsymbol_bang(t_fromsymbol *x) +{ + outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */ +} + +static void fromsymbol_float(t_fromsymbol *x, t_float f) +{ + /* CHECKED: fromsymbol: doesn't understand "int", "float" */ +} + +static void fromsymbol_symbol(t_fromsymbol *x, t_symbol *s) +{ + static char zero = 0; + char *sname = &zero; + if (s) + { + sname = s->s_name; + while (*sname == ' ' || *sname == '\t' + || *sname == '\n' || *sname == '\r') sname++; + } + if (*sname) + { + t_binbuf *bb = binbuf_new(); + int ac; + t_atom *av; + binbuf_text(bb, sname, strlen(sname)); + ac = binbuf_getnatom(bb); + av = binbuf_getvec(bb); + if (ac) + { + if (av->a_type == A_SYMBOL) + outlet_anything(((t_object *)x)->ob_outlet, + av->a_w.w_symbol, ac - 1, av + 1); + else if (av->a_type == A_FLOAT) + { + if (ac > 1) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + } + } + binbuf_free(bb); + } +} + +static void fromsymbol_list(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av) +{ + /* CHECKED: fromsymbol: doesn't understand "int", "float", + 'list <symbol>' ignored without complaining. */ +} + +static void fromsymbol_anything(t_fromsymbol *x, t_symbol *s, int ac, t_atom *av) +{ + fromsymbol_symbol(x, s); /* CHECKED */ +} + +static void *fromsymbol_new(void) +{ + t_fromsymbol *x = (t_fromsymbol *)pd_new(fromsymbol_class); + outlet_new((t_object *)x, &s_anything); + return (x); +} + +void fromsymbol_setup(void) +{ + fromsymbol_class = class_new(gensym("fromsymbol"), + (t_newmethod)fromsymbol_new, 0, + sizeof(t_fromsymbol), 0, 0); + class_addbang(fromsymbol_class, fromsymbol_bang); + class_addfloat(fromsymbol_class, fromsymbol_float); + class_addsymbol(fromsymbol_class, fromsymbol_symbol); + class_addlist(fromsymbol_class, fromsymbol_list); + class_addanything(fromsymbol_class, fromsymbol_anything); +} diff --git a/cyclone/hammer/funbuff.c b/cyclone/hammer/funbuff.c new file mode 100644 index 0000000..8d9d698 --- /dev/null +++ b/cyclone/hammer/funbuff.c @@ -0,0 +1,521 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "unstable/fragile.h" +#include "common/loud.h" +#include "common/vefl.h" +#include "hammer/tree.h" +#include "hammer/file.h" + +typedef struct _funbuff +{ + t_object x_ob; + t_canvas *x_canvas; + t_symbol *x_defname; + t_float x_value; + int x_valueset; + /* CHECKED filling with a large set, then sending 'goto', 'read', 'next'... + outputs the previous, replaced contents (same with deletion) + -- apparently a node pointer is stored, corrupt in these cases */ + t_hammernode *x_pointer; + int x_pointerset; /* set-with-goto flag */ + int x_lastdelta; + int x_embedflag; + t_hammerfile *x_filehandle; + t_hammertree x_tree; + t_outlet *x_deltaout; + t_outlet *x_bangout; +} t_funbuff; + +static t_class *funbuff_class; + +static void funbuff_dooutput(t_funbuff *x, float value, float delta) +{ + /* CHECKED lastdelta sent for 'next', 'float', 'min', 'max', + 'interp', 'find' */ + outlet_float(x->x_deltaout, delta); + outlet_float(((t_object *)x)->ob_outlet, value); +} + +static void funbuff_bang(t_funbuff *x) +{ + t_hammernode *np; + int count = 0; + int xmin = 0, xmax = 0; + t_float ymin = 0, ymax = 0; + if (np = x->x_tree.t_first) + { + /* LATER consider using extra fields, updated on the fly */ + count = 1; + xmin = np->n_index; + xmax = x->x_tree.t_last->n_index; + ymin = ymax = np->n_value; + while (np = np->n_next) + { + if (np->n_value < ymin) ymin = np->n_value; + else if (np->n_value > ymax) ymax = np->n_value; + count++; + } + } + /* format CHECKED */ + post("funbuff info: %d elements long", count); /* CHECKED 0 and 1 */ + if (count) + { + post(" -> minX= %d maxX= %d", xmin, xmax); + post(" -> minY= %g maxY= %g", ymin, ymax); + post(" -> domain= %d range= %g", xmax - xmin, ymax - ymin); + } +} + +static void funbuff_float(t_funbuff *x, t_float f) +{ + int ndx = (int)f; /* CHECKED float is silently truncated */ + t_hammernode *np; + if (x->x_valueset) + { + if (np = hammertree_insert(&x->x_tree, ndx)) + np->n_value = x->x_value; + x->x_valueset = 0; + } + else if (np = hammertree_closest(&x->x_tree, ndx, 0)) + funbuff_dooutput(x, np->n_value, x->x_lastdelta); + /* CHECKED pointer is updated -- + 'next' outputs np also in a !valueset case (it is sent twice) */ + x->x_pointer = np; + x->x_pointerset = 0; +} + +static void funbuff_ft1(t_funbuff *x, t_floatarg f) +{ + /* this is incompatible -- CHECKED float is silently truncated */ + x->x_value = f; + x->x_valueset = 1; +} + +static void funbuff_clear(t_funbuff *x) +{ + hammertree_clear(&x->x_tree, 0); + /* CHECKED valueset is not cleared */ + x->x_pointer = 0; +} + +/* LATER dirty flag handling */ +static void funbuff_embed(t_funbuff *x, t_floatarg f) +{ + x->x_embedflag = (f != 0); +} + +static void funbuff_goto(t_funbuff *x, t_floatarg f) +{ + /* CHECKED truncation */ + x->x_pointer = hammertree_closest(&x->x_tree, (int)f, 1); + x->x_pointerset = 1; /* CHECKED delta output by 'next' will be zero */ +} + +/* LATER consider using an extra field, updated on the fly */ +static void funbuff_min(t_funbuff *x) +{ + t_hammernode *np; + if (np = x->x_tree.t_first) /* CHECKED nop if empty */ + { + t_float result = np->n_value; + while (np = np->n_next) + if (np->n_value < result) result = np->n_value; + funbuff_dooutput(x, result, x->x_lastdelta); + /* CHECKED pointer not updated */ + } +} + +/* LATER consider using an extra field, updated on the fly */ +static void funbuff_max(t_funbuff *x) +{ + t_hammernode *np; + if (np = x->x_tree.t_first) /* CHECKED nop if empty */ + { + t_float result = np->n_value; + while (np = np->n_next) + if (np->n_value > result) result = np->n_value; + funbuff_dooutput(x, result, x->x_lastdelta); + /* CHECKED pointer not updated */ + } +} + +static void funbuff_next(t_funbuff *x) +{ + t_hammernode *np; + if (!x->x_tree.t_root) + return; + if (!(np = x->x_pointer)) + { + outlet_bang(x->x_bangout); + /* CHECKED banging until reset */ + return; + } + if (x->x_pointerset) + x->x_lastdelta = 0; + else if (np->n_prev) + x->x_lastdelta = np->n_index - np->n_prev->n_index; + else + x->x_lastdelta = 0; /* CHECKED corrupt delta sent here... */ + funbuff_dooutput(x, np->n_value, x->x_lastdelta); + x->x_pointer = np->n_next; + x->x_pointerset = 0; +} + +static void funbuff_set(t_funbuff *x, t_symbol *s, int ac, t_atom *av) +{ + /* CHECKED symbols somehow bashed to zeros, + decreasing x coords corrupt the funbuff -- not emulated here... */ + int i = ac; + t_atom *ap = av; + while (i--) if (ap++->a_type != A_FLOAT) + { + loud_error((t_pd *)x, "bad input (not a number) -- no data to set"); + return; + } + if (!ac || (ac % 2)) + { + /* CHECKED odd/null ac loudly rejected, current contents preserved */ + loud_error((t_pd *)x, "bad input (%s) -- no data to set", + (ac ? "odd arg count" : "no input")); + return; + } + funbuff_clear(x); /* CHECKED the contents is replaced */ + while (ac--) + { + t_hammernode *np; + if (np = hammertree_insert(&x->x_tree, (int)av++->a_w.w_float)) + np->n_value = av++->a_w.w_float; + else return; + ac--; + } +} + +static void funbuff_doread(t_funbuff *x, t_symbol *fn) +{ + t_binbuf *bb = binbuf_new(); + int ac; + t_atom *av; + char buf[MAXPDSTRING]; + canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); + binbuf_read(bb, buf, "", 0); + if ((ac = binbuf_getnatom(bb)) && + (av = binbuf_getvec(bb)) && + av->a_type == A_SYMBOL && + av->a_w.w_symbol == gensym("funbuff")) + { + post("funbuff_read: %s read successful", fn->s_name); /* CHECKED */ + funbuff_set(x, 0, ac-1, av+1); + } + else /* CHECKED no complaints... */ + loud_error((t_pd *)x, "invalid file %s", fn->s_name); + binbuf_free(bb); +} + +static void funbuff_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + funbuff_doread((t_funbuff *)z, fn); +} + +static void funbuff_dowrite(t_funbuff *x, t_symbol *fn) +{ + t_binbuf *bb = binbuf_new(); + char buf[MAXPDSTRING]; + t_hammernode *np; + binbuf_addv(bb, "s", gensym("funbuff")); + for (np = x->x_tree.t_first; np; np = np->n_next) + binbuf_addv(bb, "if", np->n_index, np->n_value); + canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); + binbuf_write(bb, buf, "", 0); + binbuf_free(bb); +} + +static void funbuff_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + funbuff_dowrite((t_funbuff *)z, fn); +} + +static void funbuff_embedhook(t_pd *z, t_binbuf *bb, t_symbol *bindsym) +{ + t_funbuff *x = (t_funbuff *)z; + if (x->x_embedflag) + { + t_hammernode *np; + binbuf_addv(bb, "ssi;", bindsym, gensym("embed"), 1); + if (np = x->x_tree.t_first) + { + binbuf_addv(bb, "ss", bindsym, gensym("set")); + for (; np; np = np->n_next) + binbuf_addv(bb, "if", np->n_index, np->n_value); + binbuf_addsemi(bb); + } + } +} + +/* CHECKED symbol arg ok */ +static void funbuff_read(t_funbuff *x, t_symbol *s) +{ + if (s && s != &s_) + funbuff_doread(x, s); + else + hammerpanel_open(x->x_filehandle); +} + +/* CHECKED symbol arg not allowed -- + a bug? but CHECKME other classes (cf seq's filetype dilemma) */ +static void funbuff_write(t_funbuff *x, t_symbol *s) +{ + if (s && s != &s_) + funbuff_dowrite(x, s); + else /* CHECKME default name */ + hammerpanel_save(x->x_filehandle, + canvas_getdir(x->x_canvas), x->x_defname); +} + +static void funbuff_delete(t_funbuff *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_FLOAT && + (ac == 1 || (ac == 2 && av[1].a_type == A_FLOAT))) + { + /* CHECKED float is silently truncated */ + int ndx = (int)av->a_w.w_float; + t_hammernode *np; + if ((np = hammertree_search(&x->x_tree, ndx)) && + (ac == 1 || np->n_value == av[1].a_w.w_float)) + { + if (np == x->x_pointer) + x->x_pointer = 0; /* CHECKED corrupt pointer left here... */ + hammertree_delete(&x->x_tree, np); + } + /* CHECKED mismatch silently ignored */ + } + else loud_messarg((t_pd *)x, s); /* CHECKED */ +} + +static void funbuff_find(t_funbuff *x, t_floatarg f) +{ + t_hammernode *np; + if (np = x->x_tree.t_first) + { + do + { + /* CHECKED lastdelta preserved */ + if (np->n_value == f) + funbuff_dooutput(x, np->n_index, x->x_lastdelta); + } + while (np = np->n_next); + /* CHECKED no bangout, no complaint if nothing found */ + } + else loud_error((t_pd *)x, "nothing to find"); /* CHECKED */ +} + +static void funbuff_dump(t_funbuff *x) +{ + t_hammernode *np; + if (np = x->x_tree.t_first) + { + do + { + x->x_lastdelta = np->n_value; /* CHECKED */ + /* float value preserved (this is incompatible) */ + funbuff_dooutput(x, np->n_index, np->n_value); + } + while (np = np->n_next); + /* CHECKED no bangout */ + } + else loud_error((t_pd *)x, "nothing to dump"); /* CHECKED */ +} + +/* CHECKME if pointer is updated */ +static void funbuff_dointerp(t_funbuff *x, t_floatarg f, int vsz, t_float *vec) +{ + t_hammernode *np1; + int trunc = (int)f; + if (trunc > f) trunc--; /* CHECKME negative floats */ + if (np1 = hammertree_closest(&x->x_tree, trunc, 0)) + { + float value = np1->n_value; + t_hammernode *np2 = np1->n_next; + if (np2) + { + float delta = (float)(np2->n_index - np1->n_index); + /* this is incompatible -- CHECKED float argument is silently + truncated (which does not make much sense here), CHECKME again */ + float frac = f - np1->n_index; + if (frac < 0 || frac >= delta) + { + bug("funbuff_dointerp"); + return; + } + frac /= delta; + if (vec) + { + /* CHECKME */ + float vpos = (vsz - 1) * frac; + int vndx = (int)vpos; + float vfrac = vpos - vndx; + if (vndx < 0 || vndx >= vsz - 1) + { + bug("funbuff_dointerp redundant test..."); + return; + } + vec += vndx; + frac = *vec + (vec[1] - *vec) * vfrac; + } + value += (np2->n_value - np1->n_value) * frac; + } + funbuff_dooutput(x, value, x->x_lastdelta); /* CHECKME !np2 */ + } + else if (np1 = hammertree_closest(&x->x_tree, trunc, 1)) + funbuff_dooutput(x, np1->n_value, x->x_lastdelta); /* CHECKME */ +} + +static void funbuff_interp(t_funbuff *x, t_floatarg f) +{ + funbuff_dointerp(x, f, 0, 0); +} + +static void funbuff_interptab(t_funbuff *x, t_symbol *s, t_floatarg f) +{ + int vsz; + t_float *vec; + if (vec = vefl_get(s, &vsz, 0, (t_pd *)x)) + { + if (vsz > 2) + funbuff_dointerp(x, f, vsz, vec); + else + funbuff_dointerp(x, f, 0, 0); + } +} + +static void funbuff_reduce(t_funbuff *x, t_floatarg f) +{ + loud_notimplemented((t_pd *)x, "reduce"); +} + +static void funbuff_select(t_funbuff *x, t_floatarg f1, t_floatarg f2) +{ + loud_notimplemented((t_pd *)x, "select"); +} + +/* CHECKED (sub)buffer's copy is stored, as expected -- + 'delete' does not modify the clipboard */ +/* CHECKED cut entire contents if no selection */ +static void funbuff_cut(t_funbuff *x) +{ + loud_notimplemented((t_pd *)x, "cut"); +} + +/* CHECKED copy entire contents if no selection */ +static void funbuff_copy(t_funbuff *x) +{ + loud_notimplemented((t_pd *)x, "copy"); +} + +static void funbuff_paste(t_funbuff *x) +{ + loud_notimplemented((t_pd *)x, "paste"); +} + +static void funbuff_undo(t_funbuff *x) +{ + /* CHECKED apparently not working in 4.07 */ + loud_notimplemented((t_pd *)x, "undo"); +} + +#ifdef HAMMERTREE_DEBUG +static void funbuff_debug(t_funbuff *x, t_floatarg f) +{ + hammertree_debug(&x->x_tree, (int)f); +} +#endif + +static void funbuff_free(t_funbuff *x) +{ + hammerfile_free(x->x_filehandle); + hammertree_clear(&x->x_tree, 0); +} + +static void *funbuff_new(t_symbol *s) +{ + t_funbuff *x = (t_funbuff *)pd_new(funbuff_class); + x->x_canvas = canvas_getcurrent(); + x->x_valueset = 0; + x->x_pointer = 0; + x->x_pointerset = 0; + x->x_lastdelta = 0; + x->x_embedflag = 0; + hammertree_init(&x->x_tree, 0); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_deltaout = outlet_new((t_object *)x, &s_float); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + if (s && s != &s_) + { + x->x_defname = s; /* CHECKME if 'read' changes this */ + funbuff_doread(x, s); + } + else x->x_defname = &s_; + x->x_filehandle = hammerfile_new((t_pd *)x, funbuff_embedhook, + funbuff_readhook, funbuff_writehook, 0); + return (x); +} + +void funbuff_setup(void) +{ + funbuff_class = class_new(gensym("funbuff"), + (t_newmethod)funbuff_new, + (t_method)funbuff_free, + sizeof(t_funbuff), 0, A_DEFSYM, 0); + class_addbang(funbuff_class, funbuff_bang); + class_addfloat(funbuff_class, funbuff_float); + class_addmethod(funbuff_class, (t_method)funbuff_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_clear, + gensym("clear"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_goto, + gensym("goto"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_min, + gensym("min"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_max, + gensym("max"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_next, + gensym("next"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_embed, + gensym("embed"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(funbuff_class, (t_method)funbuff_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(funbuff_class, (t_method)funbuff_set, + gensym("set"), A_GIMME, 0); + class_addmethod(funbuff_class, (t_method)funbuff_delete, + gensym("delete"), A_GIMME, 0); + class_addmethod(funbuff_class, (t_method)funbuff_find, + gensym("find"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_dump, + gensym("dump"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_interp, + gensym("interp"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_interptab, + gensym("interptab"), A_FLOAT, A_SYMBOL, 0); + class_addmethod(funbuff_class, (t_method)funbuff_reduce, + gensym("reduce"), A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_select, + gensym("select"), A_FLOAT, A_FLOAT, 0); + class_addmethod(funbuff_class, (t_method)funbuff_cut, + gensym("cut"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_copy, + gensym("copy"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_paste, + gensym("paste"), 0); + class_addmethod(funbuff_class, (t_method)funbuff_undo, + gensym("undo"), 0); +#ifdef HAMMERTREE_DEBUG + class_addmethod(funbuff_class, (t_method)funbuff_debug, + gensym("debug"), A_DEFFLOAT, 0); +#endif + hammerfile_setup(funbuff_class, 1); +} diff --git a/cyclone/hammer/funnel.c b/cyclone/hammer/funnel.c new file mode 100644 index 0000000..d289d8d --- /dev/null +++ b/cyclone/hammer/funnel.c @@ -0,0 +1,179 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define FUNNEL_MINSLOTS 2 +#define FUNNEL_INISIZE 32 /* LATER rethink */ +#define FUNNEL_MAXSIZE 256 + +typedef struct _funnel +{ + t_object x_ob; + int x_nslots; + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; +} t_funnel; + +typedef struct _funnel_proxy +{ + t_object p_ob; + t_outlet *p_out; /* master outlet (the same value for each slot) */ + int p_id; /* adjusted according to an offset argument */ + t_float p_value; + int p_size; /* as allocated */ + t_atom *p_message; + t_atom p_messini[FUNNEL_INISIZE]; + int p_entered; +} t_funnel_proxy; + +static t_class *funnel_class; +static t_class *funnel_proxy_class; + +static void funnel_proxy_bang(t_funnel_proxy *x) +{ + t_atom at[2]; + SETFLOAT(&at[0], x->p_id); + SETFLOAT(&at[1], x->p_value); + outlet_list(x->p_out, &s_list, 2, at); +} + +static void funnel_proxy_float(t_funnel_proxy *x, t_float f) +{ + x->p_value = f; + funnel_proxy_bang(x); +} + +static void funnel_proxy_list(t_funnel_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + int reentered = x->p_entered; + int prealloc = !reentered; + int ntotal = ac + 1; + x->p_entered = 1; + if (prealloc && ntotal > x->p_size) + { + if (ntotal > FUNNEL_MAXSIZE) + prealloc = 0; + else + { + x->p_message = grow_nodata(&ntotal, &x->p_size, x->p_message, + FUNNEL_INISIZE, x->p_messini, + sizeof(*x->p_message)); + ac = ntotal - 1; + } + } + /* LATER consider a compatibility warning if av->a_type != A_FLOAT */ + x->p_value = ((ac && av->a_type == A_FLOAT) ? av->a_w.w_float : 0); + if (prealloc) + { + SETFLOAT(x->p_message, x->p_id); + if (ac) + memcpy(x->p_message + 1, av, ac * sizeof(*x->p_message)); + outlet_list(x->p_out, &s_list, ntotal, x->p_message); + } + else + { + /* LATER consider using the stack if ntotal <= MAXSTACK */ + t_atom *buf = getbytes(ntotal * sizeof(*buf)); + if (buf) + { + SETFLOAT(buf, x->p_id); + if (ac) + memcpy(buf + 1, av, ac * sizeof(*buf)); + outlet_list(x->p_out, &s_list, ntotal, buf); + freebytes(buf, ntotal * sizeof(*buf)); + } + } + if (!reentered) x->p_entered = 0; +} + +static void funnel_bang(t_funnel *x) +{ + funnel_proxy_bang((t_funnel_proxy *)x->x_proxies[0]); +} + +static void funnel_float(t_funnel *x, t_float f) +{ + funnel_proxy_float((t_funnel_proxy *)x->x_proxies[0], f); +} + +static void funnel_list(t_funnel *x, t_symbol *s, int ac, t_atom *av) +{ + funnel_proxy_list((t_funnel_proxy *)x->x_proxies[0], s, ac, av); +} + +static void funnel_free(t_funnel *x) +{ + if (x->x_proxies) + { + int i = x->x_nslots; + while (i--) + { + t_funnel_proxy *y = (t_funnel_proxy *)x->x_proxies[i]; + if (y->p_message != y->p_messini) + freebytes(y->p_message, y->p_size * sizeof(*y->p_message)); + pd_free((t_pd *)y); + } + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } +} + +static void *funnel_new(t_floatarg f1, t_floatarg f2) +{ + t_funnel *x; + int i, nslots, nproxies = (int)f1; + int offset = (int)f2; + t_outlet *out; + t_pd **proxies; + if (nproxies < 1) /* CHECKED: one-slot funnel may be created */ + nproxies = FUNNEL_MINSLOTS; + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + return (0); + for (nslots = 0; nslots < nproxies; nslots++) + if (!(proxies[nslots] = pd_new(funnel_proxy_class))) break; + if (!nslots) + { + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_funnel *)pd_new(funnel_class); + x->x_nslots = nslots; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + out = outlet_new((t_object *)x, &s_list); + for (i = 0; i < nslots; i++) + { + t_funnel_proxy *y = (t_funnel_proxy *)proxies[i]; + y->p_out = out; + y->p_id = offset++; + y->p_value = 0; + y->p_size = FUNNEL_INISIZE; + y->p_message = y->p_messini; + y->p_entered = 0; + if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); + } + return (x); +} + +void funnel_setup(void) +{ + funnel_class = class_new(gensym("funnel"), + (t_newmethod)funnel_new, + (t_method)funnel_free, + sizeof(t_funnel), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(funnel_class, funnel_bang); + class_addfloat(funnel_class, funnel_float); + class_addlist(funnel_class, funnel_list); + /* CHECKED: funnel doesn't understand symbol, anything */ + funnel_proxy_class = class_new(gensym("_funnel_proxy"), 0, 0, + sizeof(t_funnel_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(funnel_proxy_class, funnel_proxy_bang); + class_addfloat(funnel_proxy_class, funnel_proxy_float); + class_addlist(funnel_proxy_class, funnel_proxy_list); + /* CHECKED: funnel doesn't understand symbol, anything */ +} diff --git a/cyclone/hammer/gate.c b/cyclone/hammer/gate.c new file mode 100644 index 0000000..2dbae57 --- /dev/null +++ b/cyclone/hammer/gate.c @@ -0,0 +1,147 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define GATE_MINOUTS 1 +#define GATE_MAXOUTS 100 +#define GATE_DEFOUTS 1 + +typedef struct _gate +{ + t_object x_ob; + int x_open; + t_pd *x_proxy; + int x_nouts; /* requested + 1 (as allocated) */ + t_outlet **x_outs; +} t_gate; + +typedef struct _gate_proxy +{ + t_object p_ob; + t_gate *p_master; +} t_gate_proxy; + +static t_class *gate_class; +static t_class *gate_proxy_class; + +static void gate_proxy_bang(t_gate_proxy *x) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_bang(master->x_outs[master->x_open]); +} + +static void gate_proxy_float(t_gate_proxy *x, t_float f) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_float(master->x_outs[master->x_open], f); +} + +static void gate_proxy_symbol(t_gate_proxy *x, t_symbol *s) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_symbol(master->x_outs[master->x_open], s); +} + +static void gate_proxy_pointer(t_gate_proxy *x, t_gpointer *gp) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_pointer(master->x_outs[master->x_open], gp); +} + +static void gate_proxy_list(t_gate_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_list(master->x_outs[master->x_open], s, ac, av); +} + +static void gate_proxy_anything(t_gate_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + t_gate *master = x->p_master; + if (master->x_open) + outlet_anything(master->x_outs[master->x_open], s, ac, av); +} + +static void gate_float(t_gate *x, t_float f) +{ + int i = (int)f; + if (i < 0) i = 1; + if (i >= x->x_nouts) i = x->x_nouts - 1; + x->x_open = i; +} + +static void gate_bang(t_gate *x) +{ + outlet_float(x->x_outs[1], x->x_open); +} + +static void gate_free(t_gate *x) +{ + if (x->x_proxy) pd_free(x->x_proxy); + if (x->x_outs) + freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); +} + +static void *gate_new(t_floatarg f1, t_floatarg f2) +{ + t_gate *x; + int i, nouts = (int)f1; + t_outlet **outs; + t_pd *proxy; + if (nouts < GATE_MINOUTS) + nouts = GATE_DEFOUTS; + if (nouts > GATE_MAXOUTS) + loud_incompatible_max(gate_class, GATE_MAXOUTS, "outlets"); + nouts++; /* for convenience (the cost is one pointer) */ + if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) + return (0); + if (!(proxy = pd_new(gate_proxy_class))) + { + freebytes(outs, nouts * sizeof(*outs)); + return (0); + } + x = (t_gate *)pd_new(gate_class); + x->x_nouts = nouts; + x->x_outs = outs; + x->x_proxy = proxy; + ((t_gate_proxy *)proxy)->p_master = x; + /* from max sdk manual: ``The dst parameter can be changed (or set to 0) + dynamically with the inlet_to function... The gate object uses this + technique to assign its inlet to one of several outlets, or no outlet + at all.'' We have to use a proxy, because Pd's outlet is not a t_pd + (besides, Pd does not handle inlets with null destination). */ + inlet_new((t_object *)x, proxy, 0, 0); + for (i = 1; i < nouts; i++) + x->x_outs[i] = outlet_new((t_object *)x, &s_anything); + gate_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */ + return (x); +} + +void gate_setup(void) +{ + gate_class = class_new(gensym("gate"), + (t_newmethod)gate_new, + (t_method)gate_free, + sizeof(t_gate), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(gate_class, gate_float); + class_addbang(gate_class, gate_bang); + gate_proxy_class = class_new(gensym("_gate_proxy"), 0, 0, + sizeof(t_gate_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addfloat(gate_proxy_class, gate_proxy_float); + class_addbang(gate_proxy_class, gate_proxy_bang); + class_addsymbol(gate_proxy_class, gate_proxy_symbol); + class_addpointer(gate_proxy_class, gate_proxy_pointer); + class_addlist(gate_proxy_class, gate_proxy_list); + class_addanything(gate_proxy_class, gate_proxy_anything); +} diff --git a/cyclone/hammer/grab.c b/cyclone/hammer/grab.c new file mode 100644 index 0000000..a54a3eb --- /dev/null +++ b/cyclone/hammer/grab.c @@ -0,0 +1,279 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "unstable/pd_imp.h" +#include "unstable/fragile.h" +#include "common/loud.h" + +/* LATER handle canvas grabbing (bypass) */ +/* LATER check self-grabbing */ +/* LATER fragilize */ + +/* It would be nice to have write access to o_connections field... */ + +struct _outlet +{ + t_object *o_owner; + struct _outlet *o_next; + t_outconnect *o_connections; + t_symbol *o_sym; +}; + +/* ...and to have bindlist traversal routines in Pd API. */ + +static t_class *bindlist_class = 0; + +typedef struct _bindelem +{ + t_pd *e_who; + struct _bindelem *e_next; +} t_bindelem; + +typedef struct _bindlist +{ + t_pd b_pd; + t_bindelem *b_list; +} t_bindlist; + +typedef struct _grab +{ + t_object x_ob; + t_symbol *x_target; + int x_noutlets; /* not counting right one */ + t_outconnect **x_grabcons; /* grabbed connections */ + t_outlet *x_rightout; /* right outlet */ + /* traversal helpers: */ + t_object *x_grabbed; /* currently grabbed object */ + t_outconnect *x_tograbbed; /* a connection to grabbed object */ + int x_ngrabout; /* number of grabbed object's outlets */ + t_bindelem *x_bindelem; +} t_grab; + +static t_class *grab_class; + +static void grab_start(t_grab *x) +{ + x->x_tograbbed = 0; + x->x_bindelem = 0; + if (x->x_target) + { + t_pd *proxy = x->x_target->s_thing; + t_object *ob; + if (proxy && bindlist_class) + { + if (*proxy == bindlist_class) + { + x->x_bindelem = ((t_bindlist *)proxy)->b_list; + while (x->x_bindelem) + { + if (ob = pd_checkobject(x->x_bindelem->e_who)) + { + x->x_tograbbed = + fragile_outlet_connections(ob->ob_outlet); + return; + } + x->x_bindelem = x->x_bindelem->e_next; + } + } + else if (ob = pd_checkobject(proxy)) + x->x_tograbbed = fragile_outlet_connections(ob->ob_outlet); + } + } + else x->x_tograbbed = fragile_outlet_connections(x->x_rightout); +} + +static t_pd *grab_next(t_grab *x) +{ +nextremote: + if (x->x_tograbbed) + { + t_inlet *ip; + int inno; + x->x_tograbbed = obj_nexttraverseoutlet(x->x_tograbbed, + &x->x_grabbed, &ip, &inno); + if (x->x_grabbed) + { + if (inno) + { + if (x->x_target) + loud_error((t_pd *)x, + "right outlet must feed leftmost inlet"); + else + loud_error((t_pd *)x, + "remote proxy must feed leftmost inlet"); + } + else + { + t_outlet *op; + t_outlet *goutp; + int goutno = x->x_noutlets; + x->x_ngrabout = obj_noutlets(x->x_grabbed); + if (goutno > x->x_ngrabout) goutno = x->x_ngrabout; + while (goutno--) + { + x->x_grabcons[goutno] = + obj_starttraverseoutlet(x->x_grabbed, &goutp, goutno); + goutp->o_connections = + obj_starttraverseoutlet((t_object *)x, &op, goutno); + } + return ((t_pd *)x->x_grabbed); + } + } + } + if (x->x_bindelem) while (x->x_bindelem = x->x_bindelem->e_next) + { + t_object *ob; + if (ob = pd_checkobject(x->x_bindelem->e_who)) + { + x->x_tograbbed = fragile_outlet_connections(ob->ob_outlet); + goto nextremote; + } + } + return (0); +} + +static void grab_restore(t_grab *x) +{ + t_outlet *goutp; + int goutno = x->x_noutlets; + if (goutno > x->x_ngrabout) goutno = x->x_ngrabout; + while (goutno--) + { + obj_starttraverseoutlet(x->x_grabbed, &goutp, goutno); + goutp->o_connections = x->x_grabcons[goutno]; + } +} + +static void grab_bang(t_grab *x) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + pd_bang(grabbed); + grab_restore(x); + } +} + +static void grab_float(t_grab *x, t_float f) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + pd_float(grabbed, f); + grab_restore(x); + } +} + +static void grab_symbol(t_grab *x, t_symbol *s) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + pd_symbol(grabbed, s); + grab_restore(x); + } +} + +static void grab_pointer(t_grab *x, t_gpointer *gp) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + pd_pointer(grabbed, gp); + grab_restore(x); + } +} + +static void grab_list(t_grab *x, t_symbol *s, int ac, t_atom *av) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + pd_list(grabbed, s, ac, av); + grab_restore(x); + } +} + +static void grab_anything(t_grab *x, t_symbol *s, int ac, t_atom *av) +{ + t_pd *grabbed; + grab_start(x); + while (grabbed = grab_next(x)) + { + typedmess(grabbed, s, ac, av); + grab_restore(x); + } +} + +static void grab_set(t_grab *x, t_symbol *s) +{ + if (x->x_target && s && s != &s_) x->x_target = s; +} + +/* LATER use A_GIMME */ +static void *grab_new(t_symbol *s, t_floatarg f) +{ + t_grab *x; + t_outconnect **grabcons; + int i, noutlets = (int)f; + if (noutlets < 1) noutlets = 1; + if (!(grabcons = getbytes(noutlets * sizeof(*grabcons)))) + return (0); + x = (t_grab *)pd_new(grab_class); + x->x_noutlets = noutlets; + x->x_grabcons = grabcons; + while (noutlets--) outlet_new((t_object *)x, &s_anything); + if (s && s != &s_) + { + x->x_target = s; + x->x_rightout = 0; + } + else + { + x->x_target = 0; + x->x_rightout = outlet_new((t_object *)x, &s_anything); + } + return (x); +} + +static void grab_free(t_grab *x) +{ + if (x->x_grabcons) + freebytes(x->x_grabcons, x->x_noutlets * sizeof(*x->x_grabcons)); +} + +void grab_setup(void) +{ + t_symbol *s = gensym("grab"); + grab_class = class_new(s, (t_newmethod)grab_new, + (t_method)grab_free, + sizeof(t_grab), 0, + A_DEFFLOAT, A_DEFSYMBOL, 0); + class_addfloat(grab_class, grab_float); + class_addbang(grab_class, grab_bang); + class_addsymbol(grab_class, grab_symbol); + class_addpointer(grab_class, grab_pointer); + class_addlist(grab_class, grab_list); + class_addanything(grab_class, grab_anything); + class_addmethod(grab_class, (t_method)grab_set, + gensym("set"), A_SYMBOL, 0); + if (!bindlist_class) + { + t_class *c = grab_class; + pd_bind(&grab_class, s); + pd_bind(&c, s); + if (!s->s_thing + || !(bindlist_class = *s->s_thing) + || bindlist_class->c_name != gensym("bindlist")) + error("grab: failure to initialize remote grabbing feature"); + pd_unbind(&c, s); + pd_unbind(&grab_class, s); + } +} diff --git a/cyclone/hammer/hammer.c b/cyclone/hammer/hammer.c new file mode 100644 index 0000000..a4d7efe --- /dev/null +++ b/cyclone/hammer/hammer.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "unstable/fragile.h" +#include "common/loud.h" +#include "common/port.h" +#include "hammer/file.h" +#include "../build_counter" +void allhammers_setup(void); + +typedef struct _hammer +{ + t_object x_ob; + t_symbol *x_dir; + t_hammerfile *x_filehandle; +} t_hammer; + +static t_class *hammer_class; +static int hammer_firstndx; +static int hammer_lastndx; + +static void hammer_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + import_max(fn->s_name, ""); +} + +static void hammer_import(t_hammer *x, t_symbol *fn, t_symbol *dir) +{ + if (fn && fn != &s_) + { + if (!dir || dir == &s_) dir = x->x_dir; + import_max(fn->s_name, (dir && dir != &s_) ? dir->s_name : ""); + } + else + hammerpanel_open(x->x_filehandle); +} + +static void hammer_click(t_hammer *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + hammer_import(x, 0, 0); +} + +static void hammer_bang(t_hammer *x) +{ + fragile_class_printnames("hammer classes are: ", + hammer_firstndx, hammer_lastndx); +} + +static void hammer_free(t_hammer *x) +{ + hammerfile_free(x->x_filehandle); +} + +static void *hammer_new(t_symbol *s) +{ + t_hammer *x = (t_hammer *)pd_new(hammer_class); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, hammer_readhook, 0, 0); + x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas)); + return (x); +} + +void hammer_setup(void) +{ + if (canvas_getcurrent()) + { + /* Loading the library by object creation is banned, because of a danger + of having some of the classes already loaded. LATER rethink. */ + loud_error(0, "apparently an attempt to create a 'hammer' object"); + loud_errand(0, "without having hammer library preloaded"); + return; + } + if (!zgetfn(&pd_objectmaker, gensym("cyclone"))) + post("this is hammer %s, %s %s build", + CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); + hammer_class = class_new(gensym("hammer"), + (t_newmethod)hammer_new, + (t_method)hammer_free, + sizeof(t_hammer), 0, A_DEFSYM, 0); + class_addbang(hammer_class, hammer_bang); + class_addmethod(hammer_class, (t_method)hammer_import, + gensym("import"), A_DEFSYM, A_DEFSYM, 0); + class_addmethod(hammer_class, (t_method)hammer_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(hammer_class, 0); + hammer_firstndx = fragile_class_count(); + allhammers_setup(); + hammer_lastndx = fragile_class_count() - 1; +} diff --git a/cyclone/hammer/iter.c b/cyclone/hammer/iter.c new file mode 100644 index 0000000..0aa5ef8 --- /dev/null +++ b/cyclone/hammer/iter.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a modified version of Joseph A. Sarlo's code. + The most important changes are listed in "pd-lib-notes.txt" file. */ + +/* LATER compare with iter.c from max sdk */ +/* LATER clean up buffer handling */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define ITER_INISIZE 8 /* LATER rethink */ + +typedef struct _iter +{ + t_object x_ob; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + t_symbol *x_selector; + t_atom *x_message; + t_atom x_messini[ITER_INISIZE]; +} t_iter; + +static t_class *iter_class; + +/* CHECKED: both floats and symbols */ +static void iter_dobang(t_iter *x, t_symbol *s, int ac, t_atom *av) +{ + if (s && s != &s_) + outlet_symbol(((t_object *)x)->ob_outlet, s); + while (ac--) + { + if (av->a_type == A_FLOAT) + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, av->a_w.w_symbol); + av++; + } +} + +static void iter_bang(t_iter *x) +{ + iter_dobang(x, x->x_selector, x->x_natoms, x->x_message); +} + +static void iter_float(t_iter *x, t_float f) +{ + outlet_float(((t_object *)x)->ob_outlet, f); + x->x_selector = 0; + x->x_natoms = 1; + SETFLOAT(x->x_message, f); +} + +/* CHECKME */ +static void iter_symbol(t_iter *x, t_symbol *s) +{ + outlet_symbol(((t_object *)x)->ob_outlet, s); + x->x_selector = 0; + x->x_natoms = 1; + SETSYMBOL(x->x_message, s); +} + +/* LATER gpointer */ + +static void iter_anything(t_iter *x, t_symbol *s, int ac, t_atom *av) +{ + iter_dobang(x, s, ac, av); + x->x_selector = s; + if (ac > x->x_size) + x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, + ITER_INISIZE, x->x_messini, + sizeof(*x->x_message)); + x->x_natoms = ac; + memcpy(x->x_message, av, ac * sizeof(*x->x_message)); +} + +static void iter_list(t_iter *x, t_symbol *s, int ac, t_atom *av) +{ + iter_anything(x, 0, ac, av); +} + +static void iter_free(t_iter *x) +{ + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_natoms * sizeof(*x->x_message)); +} + +static void *iter_new(void) +{ + t_iter *x = (t_iter *)pd_new(iter_class); + x->x_size = ITER_INISIZE; + x->x_natoms = 0; + x->x_message = x->x_messini; + outlet_new((t_object *)x, &s_anything); + return (x); +} + +void iter_setup(void) +{ + iter_class = class_new(gensym("iter"), + (t_newmethod)iter_new, + (t_method)iter_free, + sizeof(t_iter), 0, 0); + class_addbang(iter_class, iter_bang); + class_addfloat(iter_class, iter_float); + class_addsymbol(iter_class, iter_symbol); + class_addlist(iter_class, iter_list); + class_addanything(iter_class, iter_anything); +} diff --git a/cyclone/hammer/match.c b/cyclone/hammer/match.c new file mode 100644 index 0000000..d5b03c7 --- /dev/null +++ b/cyclone/hammer/match.c @@ -0,0 +1,216 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER compare with match.c from max sdk */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define MATCH_INISIZE 8 /* LATER rethink */ + +typedef struct _match +{ + t_object x_ob; + int x_size; /* as allocated */ + int x_patlen; /* as used */ + t_atom *x_pattern; + t_atom x_patini[MATCH_INISIZE]; + int x_quelen; + t_atom *x_queue; + t_atom x_queini[MATCH_INISIZE]; + t_atom *x_queend; + t_atom *x_queptr; /* writing head, post-incremented (oldest-pointing) */ +} t_match; + +static t_class *match_class; + +static void match_clear(t_match *x) +{ + x->x_quelen = 0; + x->x_queptr = x->x_queue; +} + +/* x->x_patlen > 0 is assumed */ +/* LATER use a lock to disable reentrant calls. I do not see any + purpose of reentering match, but lets CHECKME first... */ +static void match_checkin(t_match *x) +{ + int i, patlen = x->x_patlen; + t_atom *queptr, *pp, *qp; + if (x->x_queptr >= x->x_queend) + x->x_queptr = x->x_queue; + else x->x_queptr++; + if (x->x_quelen < patlen && ++(x->x_quelen) < patlen) + return; + + qp = queptr = x->x_queptr; + for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++) + { + if (pp->a_type == A_FLOAT) + { + if (qp->a_type != A_FLOAT || qp->a_w.w_float != pp->a_w.w_float) + break; + } + else if (pp->a_type == A_SYMBOL) + { + if (qp->a_type != A_SYMBOL || qp->a_w.w_symbol != pp->a_w.w_symbol) + break; + } + else if (pp->a_type == A_NULL) + { + if (qp->a_type == A_FLOAT || qp->a_type == A_SYMBOL) + { + /* instantiating a pattern */ + *pp = *qp; + qp->a_type = A_NULL; + } + else break; /* LATER rethink */ + } + else break; /* LATER rethink */ + if (qp >= x->x_queend) + qp = x->x_queue; + else qp++; + } + if (i == patlen) + { + pp = x->x_pattern; + if (pp->a_type == A_FLOAT) + { + if (patlen == 1) + outlet_float(((t_object *)x)->ob_outlet, pp->a_w.w_float); + else + outlet_list(((t_object *)x)->ob_outlet, &s_list, patlen, pp); + } + else /* assuming A_SYMBOL (see above) */ + { + if (pp->a_w.w_symbol == &s_symbol /* bypassing typedmess() */ + && patlen == 2 && pp[1].a_type == A_SYMBOL) + outlet_symbol(((t_object *)x)->ob_outlet, pp[1].a_w.w_symbol); + else + outlet_anything(((t_object *)x)->ob_outlet, pp->a_w.w_symbol, + patlen - 1, pp + 1); + } + /* CHECKED: no implicit clear (resolving overlapping patterns) */ + } + /* restoring a pattern */ + for (i = 0, pp = x->x_pattern; i < patlen; i++, pp++) + { + if (queptr->a_type == A_NULL) + { + queptr->a_type = pp->a_type; + pp->a_type = A_NULL; + } + if (queptr >= x->x_queend) + queptr = x->x_queue; + else queptr++; + } +} + +static void match_float(t_match *x, t_float f) +{ + if (x->x_patlen) + { + SETFLOAT(x->x_queptr, f); + match_checkin(x); + } +} + +static void match_symbol(t_match *x, t_symbol *s) +{ + if (s && s != &s_ && x->x_patlen) + { + SETSYMBOL(x->x_queptr, s); + match_checkin(x); + } +} + +/* LATER gpointer */ + +static void match_list(t_match *x, t_symbol *s, int ac, t_atom *av) +{ + while (ac--) + { + if (av->a_type == A_FLOAT) match_float(x, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) match_symbol(x, av->a_w.w_symbol); + av++; + } +} + +static void match_anything(t_match *x, t_symbol *s, int ac, t_atom *av) +{ + match_symbol(x, s); + match_list(x, 0, ac, av); +} + +static void match_set(t_match *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) /* CHECKED */ + { + t_atom *pp; + t_symbol *ps_nn; + int newlen = ac * 2; + if (newlen > x->x_size) + { + x->x_pattern = grow_nodata(&newlen, &x->x_size, x->x_pattern, + MATCH_INISIZE * 2, x->x_patini, + sizeof(*x->x_pattern)); + if (newlen == MATCH_INISIZE * 2) + { + x->x_queue = x->x_queini; + ac = MATCH_INISIZE; + } + else x->x_queue = x->x_pattern + x->x_size / 2; + } + x->x_patlen = ac; + x->x_queend = x->x_queue + ac - 1; + match_clear(x); /* CHECKED */ + memcpy(x->x_pattern, av, ac * sizeof(*x->x_pattern)); + pp = x->x_pattern; + ps_nn = gensym("nn"); + while (ac--) + { + if (pp->a_type == A_SYMBOL && pp->a_w.w_symbol == ps_nn) + pp->a_type = A_NULL; + pp++; + } + } +} + +static void match_free(t_match *x) +{ + if (x->x_pattern != x->x_patini) + freebytes(x->x_pattern, 2 * x->x_size * sizeof(*x->x_pattern)); +} + +static void *match_new(t_symbol *s, int ac, t_atom *av) +{ + t_match *x = (t_match *)pd_new(match_class); + x->x_size = MATCH_INISIZE * 2; + x->x_patlen = 0; + x->x_pattern = x->x_patini; + x->x_queue = x->x_queini; + /* x->x_queend is not used unless x->x_patlen > 0, + LATER consider chosing a more defensive way... */ + outlet_new((t_object *)x, &s_anything); + match_clear(x); + match_set(x, 0, ac, av); + return (x); +} + +void match_setup(void) +{ + match_class = class_new(gensym("match"), + (t_newmethod)match_new, + (t_method)match_free, + sizeof(t_match), 0, A_GIMME, 0); + class_addfloat(match_class, match_float); + class_addsymbol(match_class, match_symbol); + class_addlist(match_class, match_list); + class_addanything(match_class, match_anything); + class_addmethod(match_class, (t_method)match_set, + gensym("set"), A_GIMME, 0); + class_addmethod(match_class, (t_method)match_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/maximum.c b/cyclone/hammer/maximum.c new file mode 100644 index 0000000..038d8f1 --- /dev/null +++ b/cyclone/hammer/maximum.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +typedef struct _maximum +{ + t_object x_ob; + t_float x_last; + t_float x_test; +} t_maximum; + +static t_class *maximum_class; + +static void maximum_bang(t_maximum *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_last); +} + +static void maximum_float(t_maximum *x, t_float f) +{ + outlet_float(((t_object *)x)->ob_outlet, + x->x_last = (f > x->x_test ? f : x->x_test)); +} + +static void maximum_list(t_maximum *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac > 256) loud_incompatible_max(*(t_pd *)x, 256, "items"); + while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME (a warning?) */ + if (ac) + { + t_float fpick = av->a_w.w_float; + ac--; av++; + while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME */ + if (ac) + { + t_float fnext, f = av->a_w.w_float; + if (f > fpick) + { + fnext = fpick; + fpick = f; + } + else fnext = f; + ac--; av++; + while (ac--) + { + if (av->a_type == A_FLOAT) + { + f = av->a_w.w_float; + if (f > fpick) + { + fnext = fpick; + fpick = f; + } + else if (f > fnext) fnext = f; + } + /* CHECKME else */ + av++; + } + x->x_test = fnext; + outlet_float(((t_object *)x)->ob_outlet, x->x_last = fpick); + } + else maximum_float(x, fpick); /* CHECKME */ + } + /* CHECKME else */ +} + +static void *maximum_new(t_floatarg f) +{ + t_maximum *x = (t_maximum *)pd_new(maximum_class); + x->x_last = 0; /* CHECKME */ + x->x_test = f; + floatinlet_new((t_object *)x, &x->x_test); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void maximum_setup(void) +{ + maximum_class = class_new(gensym("maximum"), + (t_newmethod)maximum_new, 0, + sizeof(t_maximum), 0, A_DEFFLOAT, 0); + class_addbang(maximum_class, maximum_bang); + class_addfloat(maximum_class, maximum_float); + class_addlist(maximum_class, maximum_list); +} diff --git a/cyclone/hammer/mean.c b/cyclone/hammer/mean.c new file mode 100644 index 0000000..13d69ff --- /dev/null +++ b/cyclone/hammer/mean.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _mean +{ + t_object x_ob; + double x_accum; + unsigned x_count; + t_float x_mean; + t_outlet *x_countout; +} t_mean; + +static t_class *mean_class; + +static void mean_clear(t_mean *x) +{ + x->x_accum = 0; + x->x_count = 0; + x->x_mean = 0; +} + +static void mean_bang(t_mean *x) +{ + /* CHECKED: count is always sent (first) */ + outlet_float(x->x_countout, x->x_count); + outlet_float(((t_object *)x)->ob_outlet, x->x_mean); +} + +static void mean_float(t_mean *x, t_float f) +{ + x->x_accum += f; + if (++x->x_count) + x->x_mean = (t_float)(x->x_accum / (double)x->x_count); + else mean_clear(x); + mean_bang(x); +} + +static void mean_list(t_mean *x, t_symbol *s, int ac, t_atom *av) +{ + mean_clear(x); + while (ac--) + { + if (av->a_type == A_FLOAT) + { + x->x_accum += av->a_w.w_float; + x->x_count++; + } + av++; + } + if (x->x_count) + x->x_mean = (t_float)(x->x_accum / (double)x->x_count); + else mean_clear(x); + mean_bang(x); + /* CHECKED: no clear after list -- subsequent floats are added */ +} + +static void *mean_new(void) +{ + t_mean *x = (t_mean *)pd_new(mean_class); + mean_clear(x); + outlet_new((t_object *)x, &s_float); + x->x_countout = outlet_new((t_object *)x, &s_float); + return (x); +} + +void mean_setup(void) +{ + mean_class = class_new(gensym("mean"), + (t_newmethod)mean_new, 0, + sizeof(t_mean), 0, 0); + class_addbang(mean_class, mean_bang); + class_addfloat(mean_class, mean_float); + class_addlist(mean_class, mean_list); + class_addmethod(mean_class, (t_method)mean_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/midiflush.c b/cyclone/hammer/midiflush.c new file mode 100644 index 0000000..592d9e0 --- /dev/null +++ b/cyclone/hammer/midiflush.c @@ -0,0 +1,102 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" + +#define MIDIFLUSH_NCHANNELS 16 +#define MIDIFLUSH_NPITCHES 128 +#define MIDIFLUSH_VOIDPITCH 0xFF + +typedef struct _midiflush +{ + t_object x_ob; + unsigned char x_status; + unsigned char x_channel; + unsigned char x_pitch; + unsigned char x_notes[MIDIFLUSH_NCHANNELS][MIDIFLUSH_NPITCHES]; +} t_midiflush; + +static t_class *midiflush_class; + +static void midiflush_float(t_midiflush *x, t_float f) +{ + int ival = (int)f; + if (ival >= 0 && ival < 256) + { + unsigned char bval = ival; + outlet_float(((t_object *)x)->ob_outlet, bval); + if (bval & 0x80) + { + x->x_status = bval & 0xF0; + if (x->x_status == 0x80 || x->x_status == 0x90) + x->x_channel = bval & 0x0F; + else + x->x_status = 0; + } + else if (x->x_status) + { + if (x->x_pitch == MIDIFLUSH_VOIDPITCH) + { + x->x_pitch = bval; + return; + } + else if (x->x_status == 0x90 && bval) + { + x->x_notes[x->x_channel][x->x_pitch]++; + } + else + { + x->x_notes[x->x_channel][x->x_pitch]--; + } + } + } + x->x_pitch = MIDIFLUSH_VOIDPITCH; +} + +static void midiflush_bang(t_midiflush *x) +{ + int chn, pch; + for (chn = 0; chn < MIDIFLUSH_NCHANNELS; chn++) + { + for (pch = 0; pch < MIDIFLUSH_NPITCHES; pch++) + { + int status = 0x090 | chn; + while (x->x_notes[chn][pch]) + { + outlet_float(((t_object *)x)->ob_outlet, status); + outlet_float(((t_object *)x)->ob_outlet, pch); + outlet_float(((t_object *)x)->ob_outlet, 0); + x->x_notes[chn][pch]--; + } + } + } +} + +static void midiflush_clear(t_midiflush *x) +{ + memset(x->x_notes, 0, sizeof(x->x_notes)); +} + +static void *midiflush_new(void) +{ + t_midiflush *x = (t_midiflush *)pd_new(midiflush_class); + x->x_status = 0; /* `not a note' */ + x->x_pitch = MIDIFLUSH_VOIDPITCH; + midiflush_clear(x); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void midiflush_setup(void) +{ + midiflush_class = class_new(gensym("midiflush"), + (t_newmethod)midiflush_new, + 0, /* CHECKED: no flushout */ + sizeof(t_midiflush), 0, 0); + class_addfloat(midiflush_class, midiflush_float); + class_addbang(midiflush_class, midiflush_bang); + class_addmethod(midiflush_class, (t_method)midiflush_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/midiformat.c b/cyclone/hammer/midiformat.c new file mode 100644 index 0000000..fa0612b --- /dev/null +++ b/cyclone/hammer/midiformat.c @@ -0,0 +1,112 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _midiformat +{ + t_object x_ob; + t_float x_channel; +} t_midiformat; + +static t_class *midiformat_class; + +static int midiformat_channel(t_midiformat *x) +{ + int ch = (int)x->x_channel; + return (ch > 0 ? (ch - 1) & 0x0F : 0); +} + +static void midiformat_note(t_midiformat *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) + { + int pitch = (int)av[0].a_w.w_float; /* CHECKED: anything goes */ + int velocity = (int)av[1].a_w.w_float; + outlet_float(((t_object *)x)->ob_outlet, 0x90 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, pitch); + outlet_float(((t_object *)x)->ob_outlet, velocity); + } +} + +static void midiformat_polytouch(t_midiformat *x, + t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) + { + int touch = (int)av[0].a_w.w_float; + int key = (int)av[1].a_w.w_float; + outlet_float(((t_object *)x)->ob_outlet, 0xA0 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, key); + outlet_float(((t_object *)x)->ob_outlet, touch); + } +} + +static void midiformat_controller(t_midiformat *x, + t_symbol *s, int ac, t_atom *av) +{ + if (ac >= 2 && av[0].a_type == A_FLOAT && av[1].a_type == A_FLOAT) + { + int val = (int)av[0].a_w.w_float; + int ctl = (int)av[1].a_w.w_float; + outlet_float(((t_object *)x)->ob_outlet, 0xB0 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, ctl); + outlet_float(((t_object *)x)->ob_outlet, val); + } +} + +static void midiformat_program(t_midiformat *x, t_floatarg f) +{ + int pgm = (int)f; + outlet_float(((t_object *)x)->ob_outlet, 0xC0 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, pgm); +} + +static void midiformat_touch(t_midiformat *x, t_floatarg f) +{ + int touch = (int)f; + outlet_float(((t_object *)x)->ob_outlet, 0xD0 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, touch); +} + +static void midiformat_bend(t_midiformat *x, t_floatarg f) +{ + int val = (int)f; + outlet_float(((t_object *)x)->ob_outlet, 0xE0 | midiformat_channel(x)); + outlet_float(((t_object *)x)->ob_outlet, 0); + outlet_float(((t_object *)x)->ob_outlet, val); +} + +static void *midiformat_new(t_floatarg f) +{ + t_midiformat *x = (t_midiformat *)pd_new(midiformat_class); + x->x_channel = f; + inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst1")); + inlet_new((t_object *)x, (t_pd *)x, &s_list, gensym("lst2")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft3")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft4")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft5")); + floatinlet_new((t_object *)x, &x->x_channel); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void midiformat_setup(void) +{ + midiformat_class = class_new(gensym("midiformat"), + (t_newmethod)midiformat_new, 0, + sizeof(t_midiformat), 0, + A_DEFFLOAT, 0); + class_addlist(midiformat_class, midiformat_note); + class_addmethod(midiformat_class, (t_method)midiformat_polytouch, + gensym("lst1"), A_GIMME, 0); + class_addmethod(midiformat_class, (t_method)midiformat_controller, + gensym("lst2"), A_GIMME, 0); + class_addmethod(midiformat_class, (t_method)midiformat_program, + gensym("ft3"), A_FLOAT, 0); + class_addmethod(midiformat_class, (t_method)midiformat_touch, + gensym("ft4"), A_FLOAT, 0); + class_addmethod(midiformat_class, (t_method)midiformat_bend, + gensym("ft5"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/midiparse.c b/cyclone/hammer/midiparse.c new file mode 100644 index 0000000..9a79a39 --- /dev/null +++ b/cyclone/hammer/midiparse.c @@ -0,0 +1,132 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _midiparse +{ + t_object x_ob; + unsigned char x_ready; + unsigned char x_status; + unsigned char x_channel; + unsigned char x_data1; + t_outlet *x_polyout; + t_outlet *x_ctlout; + t_outlet *x_pgmout; + t_outlet *x_touchout; + t_outlet *x_bendout; + t_outlet *x_chanout; +} t_midiparse; + +static t_class *midiparse_class; + +static void midiparse_clear(t_midiparse *x) +{ + x->x_status = 0; + x->x_ready = 0; +} + +static void midiparse_float(t_midiparse *x, t_float f) +{ + int ival = (int)f; /* CHECKED */ + if (ival < 0) + { + /* CHECKME */ + return; + } + if (ival < 256) /* CHECKED clear if input over 255 */ + { + unsigned char bval = ival; + if (bval & 0x80) + { + unsigned char status = bval & 0xF0; + if (status == 0xF0) + { + /* CHECKED no such test in max -- this is incompatible, + but real-time messages are out-of-band, and they + should be ignored here. LATER rethink the 0xFE case. */ + if (bval < 0xF8) + midiparse_clear(x); + } + else + { + x->x_status = status; + x->x_channel = bval & 0x0F; + x->x_ready = (status == 0xC0 || status == 0xD0); + } + } + else if (x->x_ready) + { + t_atom at[2]; + x->x_ready = 0; + outlet_float(x->x_chanout, x->x_channel + 1); + switch (x->x_status) + { + case 0x80: + SETFLOAT(&at[0], x->x_data1); + SETFLOAT(&at[1], 0); + outlet_list(((t_object *)x)->ob_outlet, 0, 2, at); + break; + case 0x90: + SETFLOAT(&at[0], x->x_data1); + SETFLOAT(&at[1], bval); + outlet_list(((t_object *)x)->ob_outlet, 0, 2, at); + break; + case 0xA0: + SETFLOAT(&at[0], bval); + SETFLOAT(&at[1], x->x_data1); + outlet_list(x->x_polyout, 0, 2, at); + break; + case 0xB0: + SETFLOAT(&at[0], bval); + SETFLOAT(&at[1], x->x_data1); + outlet_list(x->x_ctlout, 0, 2, at); + break; + case 0xC0: + outlet_float(x->x_pgmout, bval); + x->x_ready = 1; + break; + case 0xD0: + outlet_float(x->x_touchout, bval); + x->x_ready = 1; + break; + case 0xE0: + /* CHECKED: ignores data1 */ + outlet_float(x->x_bendout, bval); + break; + default:; + } + } + else if (x->x_status) + { + x->x_data1 = bval; /* CHECKED key #0 accepted */ + x->x_ready = 1; + } + } + else midiparse_clear(x); +} + +static void *midiparse_new(void) +{ + t_midiparse *x = (t_midiparse *)pd_new(midiparse_class); + outlet_new((t_object *)x, &s_list); + x->x_polyout = outlet_new((t_object *)x, &s_list); + x->x_ctlout = outlet_new((t_object *)x, &s_list); + x->x_pgmout = outlet_new((t_object *)x, &s_float); + x->x_touchout = outlet_new((t_object *)x, &s_float); + x->x_bendout = outlet_new((t_object *)x, &s_float); + x->x_chanout = outlet_new((t_object *)x, &s_float); + midiparse_clear(x); + return (x); +} + +void midiparse_setup(void) +{ + midiparse_class = class_new(gensym("midiparse"), + (t_newmethod)midiparse_new, 0, + sizeof(t_midiparse), 0, 0); + class_addbang(midiparse_class, midiparse_clear); + class_addfloat(midiparse_class, midiparse_float); + /* CHECKED autocasting lists to floats */ +} diff --git a/cyclone/hammer/minimum.c b/cyclone/hammer/minimum.c new file mode 100644 index 0000000..466b6f8 --- /dev/null +++ b/cyclone/hammer/minimum.c @@ -0,0 +1,88 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +typedef struct _minimum +{ + t_object x_ob; + t_float x_last; + t_float x_test; +} t_minimum; + +static t_class *minimum_class; + +static void minimum_bang(t_minimum *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_last); +} + +static void minimum_float(t_minimum *x, t_float f) +{ + outlet_float(((t_object *)x)->ob_outlet, + x->x_last = (f < x->x_test ? f : x->x_test)); +} + +static void minimum_list(t_minimum *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac > 256) loud_incompatible_max(*(t_pd *)x, 256, "items"); + while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME (a warning?) */ + if (ac) + { + t_float fpick = av->a_w.w_float; + ac--; av++; + while (ac && av->a_type != A_FLOAT) ac--, av++; /* CHECKME */ + if (ac) + { + t_float fnext, f = av->a_w.w_float; + if (f < fpick) + { + fnext = fpick; + fpick = f; + } + else fnext = f; + ac--; av++; + while (ac--) + { + if (av->a_type == A_FLOAT) + { + f = av->a_w.w_float; + if (f < fpick) + { + fnext = fpick; + fpick = f; + } + else if (f < fnext) fnext = f; + } + /* CHECKME else */ + av++; + } + x->x_test = fnext; + outlet_float(((t_object *)x)->ob_outlet, x->x_last = fpick); + } + else minimum_float(x, fpick); /* CHECKME */ + } + /* CHECKME else */ +} + +static void *minimum_new(t_floatarg f) +{ + t_minimum *x = (t_minimum *)pd_new(minimum_class); + x->x_last = 0; /* CHECKME */ + x->x_test = f; + floatinlet_new((t_object *)x, &x->x_test); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void minimum_setup(void) +{ + minimum_class = class_new(gensym("minimum"), + (t_newmethod)minimum_new, 0, + sizeof(t_minimum), 0, A_DEFFLOAT, 0); + class_addbang(minimum_class, minimum_bang); + class_addfloat(minimum_class, minimum_float); + class_addlist(minimum_class, minimum_list); +} diff --git a/cyclone/hammer/mousefilter.c b/cyclone/hammer/mousefilter.c new file mode 100644 index 0000000..e2e3cc5 --- /dev/null +++ b/cyclone/hammer/mousefilter.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "hammer/gui.h" + +typedef struct _mousefilter +{ + t_object x_ob; + int x_isup; + int x_ispending; + t_float x_value; +} t_mousefilter; + +static t_class *mousefilter_class; + +static void mousefilter_float(t_mousefilter *x, t_float f) +{ + if (x->x_isup) + outlet_float(((t_object *)x)->ob_outlet, f); + else + { + x->x_ispending = 1; + x->x_value = f; + } +} + +static void mousefilter_anything(t_mousefilter *x, + t_symbol *s, int ac, t_atom *av) +{ + /* dummy method, filtering out those messages from gui, + which are not handled explicitly */ +} + +static void mousefilter_doup(t_mousefilter *x, t_floatarg f) +{ + if ((x->x_isup = (int)f) && x->x_ispending) + { + x->x_ispending = 0; + outlet_float(((t_object *)x)->ob_outlet, x->x_value); + } +} + +static void mousefilter_free(t_mousefilter *x) +{ + hammergui_unbindmouse((t_pd *)x); +} + +static void *mousefilter_new(void) +{ + t_mousefilter *x = (t_mousefilter *)pd_new(mousefilter_class); + x->x_isup = 0; /* LATER rethink */ + x->x_ispending = 0; + outlet_new((t_object *)x, &s_float); + hammergui_bindmouse((t_pd *)x); + return (x); +} + +void mousefilter_setup(void) +{ + mousefilter_class = class_new(gensym("mousefilter"), + (t_newmethod)mousefilter_new, + (t_method)mousefilter_free, + sizeof(t_mousefilter), 0, 0); + class_addfloat(mousefilter_class, mousefilter_float); + class_addanything(mousefilter_class, mousefilter_anything); + class_addmethod(mousefilter_class, (t_method)mousefilter_doup, + gensym("_up"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/next.c b/cyclone/hammer/next.c new file mode 100644 index 0000000..3fe7d6e --- /dev/null +++ b/cyclone/hammer/next.c @@ -0,0 +1,58 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +//#define NEXT_USEEVENTNO + +typedef struct _next +{ + t_object x_ob; +#ifdef NEXT_USEEVENTNO + int x_lastevent; +#else + double x_lastevent; +#endif + t_outlet *x_out2; +} t_next; + +static t_class *next_class; + +/* CHECKME first call, CHECKME if the outlets are not swapped */ +static void next_anything(t_next *x, t_symbol *s, int ac, t_atom *av) +{ +#ifdef NEXT_USEEVENTNO + int nextevent = sys_geteventno(); +#else + double nextevent = clock_getlogicaltime(); +#endif + if (x->x_lastevent == nextevent) + outlet_bang(x->x_out2); + else + { + x->x_lastevent = nextevent; + outlet_bang(((t_object *)x)->ob_outlet); + } +} + +static void *next_new(void) +{ + t_next *x = (t_next *)pd_new(next_class); + outlet_new((t_object *)x, &s_bang); + x->x_out2 = outlet_new((t_object *)x, &s_bang); +#ifdef NEXT_USEEVENTNO + x->x_lastevent = sys_geteventno(); +#else + x->x_lastevent = clock_getlogicaltime(); +#endif + return (x); +} + +void next_setup(void) +{ + next_class = class_new(gensym("next"), + (t_newmethod)next_new, 0, + sizeof(t_next), 0, 0); + class_addanything(next_class, next_anything); +} diff --git a/cyclone/hammer/offer.c b/cyclone/hammer/offer.c new file mode 100644 index 0000000..3823c85 --- /dev/null +++ b/cyclone/hammer/offer.c @@ -0,0 +1,94 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" +#include "hammer/tree.h" + +/* As a class `derived' from the common hammertree code (also in funbuff), + offer uses the auxiliary list, generally not needed here. + As a side-effect, it gets a bonus of a small speedup of deletion, + and a penalty of a small slowdown of insertion. */ + +typedef struct _offer +{ + t_object x_ob; + t_float x_value; + int x_valueset; + t_hammertree x_tree; +} t_offer; + +static t_class *offer_class; + +static void offer_float(t_offer *x, t_float f) +{ + int ndx; + if (loud_checkint((t_pd *)x, f, &ndx, &s_float)) /* CHECKED */ + { + t_hammernode *np; + if (x->x_valueset) + { + if (np = hammertree_insert(&x->x_tree, ndx)) + np->n_value = x->x_value; + x->x_valueset = 0; + } + else if (np = hammertree_search(&x->x_tree, ndx)) + { + outlet_float(((t_object *)x)->ob_outlet, np->n_value); + hammertree_delete(&x->x_tree, np); + } + } +} + +static void offer_ft1(t_offer *x, t_floatarg f) +{ + /* this is incompatible -- CHECKED float is silently truncated */ + x->x_value = f; + x->x_valueset = 1; +} + +static void offer_clear(t_offer *x) +{ + hammertree_clear(&x->x_tree, 0); + /* CHECKED valueset is not cleared */ +} + +#ifdef HAMMERTREE_DEBUG +static void offer_debug(t_offer *x, t_floatarg f) +{ + hammertree_debug(&x->x_tree, (int)f); +} +#endif + +static void offer_free(t_offer *x) +{ + hammertree_clear(&x->x_tree, 0); +} + +static void *offer_new(void) +{ + t_offer *x = (t_offer *)pd_new(offer_class); + x->x_valueset = 0; + hammertree_init(&x->x_tree, 0); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void offer_setup(void) +{ + offer_class = class_new(gensym("offer"), + (t_newmethod)offer_new, + (t_method)offer_free, + sizeof(t_offer), 0, 0); + class_addfloat(offer_class, offer_float); + class_addmethod(offer_class, (t_method)offer_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(offer_class, (t_method)offer_clear, + gensym("clear"), 0); +#ifdef HAMMERTREE_DEBUG + class_addmethod(offer_class, (t_method)offer_debug, + gensym("debug"), A_DEFFLOAT, 0); +#endif +} diff --git a/cyclone/hammer/onebang.c b/cyclone/hammer/onebang.c new file mode 100644 index 0000000..a4132dc --- /dev/null +++ b/cyclone/hammer/onebang.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _onebang +{ + t_object x_ob; + int x_isopen; +} t_onebang; + +static t_class *onebang_class; + +static void onebang_bang(t_onebang *x) +{ + if (x->x_isopen) + { + outlet_bang(((t_object *)x)->ob_outlet); + x->x_isopen = 0; + } +} + +static void onebang_bang1(t_onebang *x) +{ + x->x_isopen = 1; +} + +static void *onebang_new(t_floatarg f) +{ + t_onebang *x = (t_onebang *)pd_new(onebang_class); + x->x_isopen = ((int)f != 0); /* CHECKED */ + inlet_new((t_object *)x, (t_pd *)x, &s_bang, gensym("bang1")); + outlet_new((t_object *)x, &s_bang); + return (x); +} + +void onebang_setup(void) +{ + onebang_class = class_new(gensym("onebang"), + (t_newmethod)onebang_new, 0, + sizeof(t_onebang), 0, A_DEFFLOAT, 0); + class_addbang(onebang_class, onebang_bang); + class_addmethod(onebang_class, (t_method)onebang_bang1, + gensym("bang1"), 0); +} diff --git a/cyclone/hammer/past.c b/cyclone/hammer/past.c new file mode 100644 index 0000000..eb29c8e --- /dev/null +++ b/cyclone/hammer/past.c @@ -0,0 +1,154 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKED: + bang for a float at > (refman error: >=) + bang for a list if all >= (refman page says the same) + bang for a list if any is >, even if the rest (but not previous) is < + well... +*/ + +#include "m_pd.h" +#include "common/loud.h" +#include "common/grow.h" + +#define PAST_MAXSIZE 8 /* CHECKED */ + +typedef struct past +{ + t_object x_ob; + int x_low; + int x_size; /* as allocated */ + int x_nthresh; /* as used */ + t_atom *x_thresh; + t_atom x_thrini[PAST_MAXSIZE]; +} t_past; + +static t_class *past_class; + +static int past_compare(t_past *x, t_float f, t_atom *ap) +{ + if (ap->a_type == A_FLOAT) + { + if (f > ap->a_w.w_float) + return (1); + else if (f == ap->a_w.w_float) + return (0); + else + return (-1); + } + else /* CHECKED */ + { + if (f > 0.) + return (1); + else if (f == 0.) + return (0); + else + return (-1); + } +} + +static void past_float(t_past *x, t_float f) +{ + if (x->x_nthresh == 1) + { + if (past_compare(x, f, x->x_thresh) > 0) /* CHECKED: equal is low */ + { + if (x->x_low) + { + x->x_low = 0; + outlet_bang(((t_object *)x)->ob_outlet); + } + } + else x->x_low = 1; + } + else if (past_compare(x, f, x->x_thresh) < 0) x->x_low = 1; +} + +/* CHECKME: x_low handling */ +static void past_list(t_past *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && ac <= x->x_nthresh) + { + int result; + t_atom *vp = x->x_thresh; + if (av->a_type == A_FLOAT + && (result = past_compare(x, av->a_w.w_float, vp)) >= 0) + { + if (!result) + { + for (ac--, av++, vp++; ac; ac--, av++, vp++) + { + if (av->a_type != A_FLOAT + || (result = + past_compare(x, av->a_w.w_float, vp++)) < 0) + { + x->x_low = 1; + return; + } + if (result) break; + } + } + if (x->x_low) + { + x->x_low = 0; + outlet_bang(((t_object *)x)->ob_outlet); + } + } + else x->x_low = 1; + } +} + +static void past_clear(t_past *x) +{ + x->x_low = 1; +} + +static void past_set(t_past *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_atom *vp = x->x_thresh; + if (ac > x->x_size) + { + loud_incompatible_max(past_class, PAST_MAXSIZE, "guard points"); + x->x_thresh = grow_nodata(&ac, &x->x_size, x->x_thresh, + PAST_MAXSIZE, x->x_thrini, + sizeof(*x->x_thresh)); + } + x->x_nthresh = ac; + while (ac--) *vp++ = *av++; + /* CHECKED: x_low is not set here */ + } +} + +static void past_free(t_past *x) +{ + if (x->x_thresh != x->x_thrini) + freebytes(x->x_thresh, x->x_size * sizeof(*x->x_thresh)); +} + +static void *past_new(t_symbol *s, int ac, t_atom *av) +{ + t_past *x = (t_past *)pd_new(past_class); + x->x_low = 1; + x->x_nthresh = 0; + x->x_size = PAST_MAXSIZE; + x->x_thresh = x->x_thrini; + outlet_new((t_object *)x, &s_bang); + past_set(x, 0, ac, av); + return (x); +} + +void past_setup(void) +{ + past_class = class_new(gensym("past"), + (t_newmethod)past_new, + (t_method)past_free, + sizeof(t_past), 0, A_GIMME, 0); + class_addfloat(past_class, past_float); + class_addlist(past_class, past_list); + class_addmethod(past_class, (t_method)past_clear, gensym("clear"), 0); + class_addmethod(past_class, (t_method)past_set, gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/pd-lib-notes.txt b/cyclone/hammer/pd-lib-notes.txt new file mode 100644 index 0000000..8b45005 --- /dev/null +++ b/cyclone/hammer/pd-lib-notes.txt @@ -0,0 +1,61 @@ +modifications to Joseph A. Sarlo's code (formerly part of `pd-lib') +------------------------------------------------------------------- + +LATER: more testing, max-checking, resolving reentrancy, gc, etc. + +accum: only cosmetics + +bangbang: +- if argument > 2 the array is dynamically allocated +- if argument > 40 (max in max), a warning is printed +- accepts any message + +Bucket: +- arrays are dynamically allocated, no upper limit (max has no limit too) +- outlets output in right-to-left order +- added: 'set' method, 'l2r' and 'r2l' aliases + +buddy: coded from scratch +- using array of proxy objects (accepting any message) +- no upper limit for number of slots + +capture: coded from scratch +- text editor, savepanel +- any size +- circular buffering + +counter (rewritten entirely): +- using proxies to handle bangs and floats in other inlets than first +- new `engine', counter_dobang(), coded from scratch +- various adjustments of things that turned out to work differently in max, + too many to list here (and probably more are required -- please let me know!) + +cycle: +- the array of outlets is dynamically allocated +- fixing cycle_list()'s bugs +- accepting (and sending) both floats and symbols, accepting anything +- 'thresh' and 'set' methods +- event-sensitive mode emulation (a temporary hack) + +Decode (rewritten entirely): +- if argument > 8 the array is dynamically allocated (with a warning) +- all outlets deliver after any action +- outlets output in right-to-left order +- while in all-off mode, input is stored, not ignored +- out-of-range input is clipped, not ignored + +Histo (rewritten entirely): +- creation argument added (size) +- the array is dynamically allocated, no upper limit (max has no limit too) +- check if input is in range, to prevent crashes :) +- 'bang' method + +iter: +- different method of memory allocation +- dripping both floats and symbols (max4 feature) +- 'anything' method + +match: coded from scratch +- matching stream of both floats and symbols (max4 feature) +- scanning all kinds of messages, not only separate floats +- recognizing overlapping patterns diff --git a/cyclone/hammer/poltocar.c b/cyclone/hammer/poltocar.c new file mode 100644 index 0000000..486eead --- /dev/null +++ b/cyclone/hammer/poltocar.c @@ -0,0 +1,44 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sinf sin +#define cosf cos +#endif + +typedef struct _poltocar +{ + t_object x_ob; + t_float x_phase; + t_outlet *x_out2; +} t_poltocar; + +static t_class *poltocar_class; + +static void poltocar_float(t_poltocar *x, t_float f) +{ + outlet_float(x->x_out2, f * sinf(x->x_phase)); + outlet_float(((t_object *)x)->ob_outlet, f * cosf(x->x_phase)); +} + +static void *poltocar_new(void) +{ + t_poltocar *x = (t_poltocar *)pd_new(poltocar_class); + floatinlet_new((t_object *)x, &x->x_phase); + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void poltocar_setup(void) +{ + poltocar_class = class_new(gensym("poltocar"), + (t_newmethod)poltocar_new, 0, + sizeof(t_poltocar), 0, 0); + class_addfloat(poltocar_class, poltocar_float); +} diff --git a/cyclone/hammer/prepend.c b/cyclone/hammer/prepend.c new file mode 100644 index 0000000..567bb73 --- /dev/null +++ b/cyclone/hammer/prepend.c @@ -0,0 +1,258 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/grow.h" + +#define PREPEND_INISIZE 32 /* LATER rethink */ +#define PREPEND_MAXSIZE 256 + +typedef struct _prepend +{ + t_object x_ob; + t_symbol *x_selector; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + t_atom *x_message; + t_atom x_messini[PREPEND_INISIZE]; + int x_entered; + int x_auxsize; + t_atom *x_auxbuf; +} t_prepend; + +static t_class *prepend_class; + +/* Usually a preallocation method is used, except in special cases of: + 1) reentrant output request, or 2) an output request which would cause + resizing to more than MAXSIZE (no such limit for a 'set' message). + In both special cases, a temporary output buffer is allocated. + A separately preallocated output buffer is not used, thus avoiding + memcpying of the stored message (a small performance gain when the + preallocation method is chosen). Instead, self-invoked 'set' + messages are postponed, using an auxiliary buffer. +*/ + +static void prepend_dooutput(t_prepend *x, t_symbol *s, int ac, t_atom *av) +{ + if (s == &s_float) + { + if (ac > 1) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + } + else if (s == &s_list) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else if (s) + /* CHECKED: 'bang' is prepended -- we cannot do so... + ('symbol' cannot be compatible too) */ + { + outlet_anything(((t_object *)x)->ob_outlet, s, ac, av); + } +} + +static void prepend_anything(t_prepend *x, t_symbol *s, int ac, t_atom *av) +{ + int reentered = x->x_entered; + int prealloc = !reentered; + int ntotal = x->x_natoms + ac; + t_atom *buf; + x->x_entered = 1; + if (s == &s_) s = 0; + if (s) + ntotal++; + if (prealloc && ntotal > x->x_size) + { + if (ntotal > PREPEND_MAXSIZE) + prealloc = 0; + else + { + int nrequested = ntotal; + x->x_message = grow_withdata(&nrequested, &x->x_natoms, + &x->x_size, x->x_message, + PREPEND_INISIZE, x->x_messini, + sizeof(*x->x_message)); + prealloc = (nrequested == ntotal); + } + } + if (prealloc) + { + buf = x->x_message + x->x_natoms; + if (s) + { + SETSYMBOL(buf, s); + buf++; + } + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + prepend_dooutput(x, x->x_selector, ntotal, x->x_message); + } + else + { + /* LATER consider using the stack if ntotal <= MAXSTACK */ + if (buf = getbytes(ntotal * sizeof(*buf))) + { + t_atom *bp = buf + x->x_natoms; + if (x->x_natoms) + memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf)); + if (s) + { + SETSYMBOL(bp, s); + bp++; + } + if (ac) + memcpy(bp, av, ac * sizeof(*bp)); + prepend_dooutput(x, x->x_selector, ntotal, buf); + freebytes(buf, ntotal * sizeof(*buf)); + } + } + if (!reentered) + { + x->x_entered = 0; + if (x->x_auxbuf) + { + if (x->x_auxsize <= x->x_size) + { + x->x_natoms = x->x_auxsize / 2; + memcpy(x->x_message, x->x_auxbuf, + x->x_natoms * sizeof(*x->x_message)); + freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); + } + else + { + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); + x->x_size = x->x_auxsize; + x->x_message = x->x_auxbuf; + x->x_natoms = x->x_auxsize / 2; + } + x->x_auxbuf = 0; + } + } +} + +static void prepend_bang(t_prepend *x) +{ + t_atom at; + SETSYMBOL(&at, &s_bang); /* CHECKED */ + prepend_anything(x, 0, 1, &at); +} + +static void prepend_float(t_prepend *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + prepend_anything(x, 0, 1, &at); +} + +static void prepend_symbol(t_prepend *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + prepend_anything(x, 0, 1, &at); +} + +/* LATER gpointer */ + +static void prepend_list(t_prepend *x, t_symbol *s, int ac, t_atom *av) +{ + prepend_anything(x, 0, ac, av); +} + +static void prepend_set(t_prepend *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + int newsize; + if (av->a_type == A_FLOAT) + { + if (ac > 1) x->x_selector = &s_list; + else x->x_selector = &s_float; + } + else if (av->a_type == A_SYMBOL) + { + x->x_selector = av->a_w.w_symbol; + ac--; + av++; + } + else + return; /* LATER rethink */ + newsize = ac * 2; + if (x->x_entered) + { + if (x->x_auxbuf) + { + loud_warning((t_pd *)x, "'set' message overridden"); + freebytes(x->x_auxbuf, x->x_auxsize * sizeof(*x->x_auxbuf)); + x->x_auxsize = 0; + } + if (x->x_auxbuf = getbytes(newsize * sizeof(*x->x_auxbuf))) + { + memcpy(x->x_auxbuf, av, ac * sizeof(*x->x_auxbuf)); + x->x_auxsize = newsize; + } + } + else + { + t_atom *ap; + if (newsize > x->x_size) + { + int sz = newsize; + x->x_message = grow_nodata(&sz, &x->x_size, x->x_message, + PREPEND_INISIZE, x->x_messini, + sizeof(*x->x_message)); + if (sz != newsize) + ac = sz / 2; /* LATER rethink */ + } + x->x_natoms = ac; + ap = x->x_message; + while (ac--) *ap++ = *av++; + } + } +} + +static void prepend_free(t_prepend *x) +{ + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); +} + +static void *prepend_new(t_symbol *s, int ac, t_atom *av) +{ + t_prepend *x = (t_prepend *)pd_new(prepend_class); + x->x_selector = 0; + x->x_size = PREPEND_INISIZE; + x->x_natoms = 0; + x->x_message = x->x_messini; + x->x_auxbuf = 0; + x->x_entered = 0; + if (!ac) + { + loud_incompatible(prepend_class, + "creating an object without an argument"); + /* CHECKED: this is not compatible -- in max an object without an outlet + is created, and there is no warning if loading from a file. */ + } + outlet_new((t_object *)x, &s_anything); + prepend_set(x, 0, ac, av); + return (x); +} + +void prepend_setup(void) +{ + prepend_class = class_new(gensym("prepend"), + (t_newmethod)prepend_new, + (t_method)prepend_free, + sizeof(t_prepend), 0, + A_GIMME, 0); + class_addbang(prepend_class, prepend_bang); + class_addfloat(prepend_class, prepend_float); + class_addsymbol(prepend_class, prepend_symbol); + class_addlist(prepend_class, prepend_list); + class_addanything(prepend_class, prepend_anything); + class_addmethod(prepend_class, (t_method)prepend_set, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/prob.c b/cyclone/hammer/prob.c new file mode 100644 index 0000000..5227870 --- /dev/null +++ b/cyclone/hammer/prob.c @@ -0,0 +1,312 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/rand.h" +#include "hammer/file.h" + +/* CHECKED: no preallocation. Apparently, it looks like if the new + state-entries were added to the list's head, and the new transition-entries + were added to the sublist's head. No sorting of any kind. */ + +#define PROB_DEBUG 0 + +typedef struct _probtrans +{ + int tr_value; /* state (if a header trans), or suffix value (otherwise) */ + int tr_count; /* (a total in case of a header trans) */ + struct _probtrans *tr_suffix; /* header trans of a suffix state */ + struct _probtrans *tr_nexttrans; /* next trans of this state */ + struct _probtrans *tr_nextstate; /* header trans of a next state */ +} t_probtrans; + +typedef struct _prob +{ + t_object x_ob; + t_probtrans *x_translist; + t_probtrans *x_state; + t_probtrans *x_default; + int x_embedmode; + int x_silent; + unsigned int x_seed; + t_outlet *x_bangout; + t_hammerfile *x_filehandle; +} t_prob; + +static t_class *prob_class; + +static t_probtrans *prob_findstate(t_prob *x, int value, int complain) +{ + t_probtrans *state; + for (state = x->x_translist; state; state = state->tr_nextstate) + if (state->tr_value == value) + break; + if (!state && complain && !x->x_silent) + loud_error((t_pd *)x, "no state %d", value); /* CHECKED */ + return (state); +} + +static void prob_reset(t_prob *x, t_floatarg f) +{ + int value = (int)f; /* CHECKED: float converted to int */ + t_probtrans *state = prob_findstate(x, value, 1); + if (state) /* CHECKED */ + { + x->x_default = state; + /* CHECKED (sort of): */ + if (!x->x_state->tr_nexttrans) + x->x_state = state; + } +} + +/* +CHECKED: embedmode off: +#N prob; +#P newobj ... prob; + +CHECKED: embedmode on, after clear: +#N prob; +#T embed 1; +#P newobj ... prob; + +CHECKED: embedmode on, filled: +#N prob; +#T <preffix> <suffix> <count> +... +#T embed 1; +#T reset <default>; (if set) +#P newobj ... prob; +*/ +static void prob_embed(t_prob *x, t_floatarg f) +{ + x->x_embedmode = ((int)f != 0); + if (x->x_embedmode) + loud_incompatible(prob_class, "embedding not supported (yet)..."); +} + +static void prob_clear(t_prob *x) +{ + t_probtrans *state, *nextstate; + for (state = x->x_translist; state; state = nextstate) + { + t_probtrans *trans, *nexttrans; + for (trans = state->tr_nexttrans; trans; trans = nexttrans) + { + nexttrans = trans->tr_nexttrans; + freebytes(trans, sizeof(*trans)); + } + nextstate = state->tr_nextstate; + freebytes(state, sizeof(*state)); + } + x->x_translist = 0; + x->x_state = 0; + x->x_default = 0; /* CHECKED: default number is not kept */ + /* CHECKED embedmode is kept */ +} + +/* CHECKED */ +static void prob_dump(t_prob *x) +{ + t_probtrans *state; + post("transition probabilities:"); + for (state = x->x_translist; state; state = state->tr_nextstate) + { + t_probtrans *trans; + for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans) + post(" from %3d to %3d: %d", + state->tr_value, trans->tr_value, trans->tr_count); + /* CHECKED: dead-ends are reported */ + post("total weights for state %d: %d", + state->tr_value, state->tr_count); + } +} + +static void prob_bang(t_prob *x) +{ + if (x->x_state) /* CHECKED: no output after clear */ + { + int rnd = rand_int(&x->x_seed, x->x_state->tr_count); + t_probtrans *trans = x->x_state->tr_nexttrans; + if (trans) + { + for (trans = x->x_state->tr_nexttrans; trans; + trans = trans->tr_nexttrans) + if ((rnd -= trans->tr_count) < 0) + break; + if (trans) + { + t_probtrans *nextstate = trans->tr_suffix; + if (nextstate) + { + outlet_float(((t_object *)x)->ob_outlet, + nextstate->tr_value); + x->x_state = nextstate; + } + else bug("prob_bang: void suffix"); + } + else bug("prob_bang: search overflow"); + } + else + { + outlet_bang(x->x_bangout); + if (x->x_default) /* CHECKED: stays at dead-end if no default */ + x->x_state = x->x_default; + } + } +} + +static void prob_float(t_prob *x, t_float f) +{ + int value; + if (loud_checkint((t_pd *)x, f, &value, &s_float)) /* CHECKED */ + { + t_probtrans *state = prob_findstate(x, value, 1); + if (state) /* CHECKED */ + x->x_state = state; + } +} + +static void prob_list(t_prob *x, t_symbol *s, int ac, t_atom *av) +{ + int prefval, suffval, count; + if (ac == 3 && av->a_type == A_FLOAT + && av[1].a_type == A_FLOAT && av[2].a_type == A_FLOAT + && (prefval = (int)av->a_w.w_float) == av->a_w.w_float + && (suffval = (int)av[1].a_w.w_float) == av[1].a_w.w_float + && (count = (int)av[2].a_w.w_float) == av[2].a_w.w_float) + { + t_probtrans *prefix = prob_findstate(x, prefval, 0); + t_probtrans *suffix = prob_findstate(x, suffval, 0); + t_probtrans *trans; + if (prefix && suffix) + { + for (trans = prefix->tr_nexttrans; trans; + trans = trans->tr_nexttrans) + if (trans->tr_suffix == suffix) + break; + if (trans) + { + /* the transition already exists... */ + prefix->tr_count += (count - trans->tr_count); + trans->tr_count = count; + return; + } + } + if (!prefix) + { + if (!(prefix = getbytes(sizeof(*prefix)))) + return; + prefix->tr_value = prefval; + prefix->tr_count = 0; + prefix->tr_suffix = 0; + prefix->tr_nexttrans = 0; + prefix->tr_nextstate = x->x_translist; + x->x_translist = prefix; + if (suffval == prefval) + suffix = prefix; + } + if (!suffix) + { + if (!(suffix = getbytes(sizeof(*suffix)))) + return; + suffix->tr_value = suffval; + suffix->tr_count = 0; + suffix->tr_suffix = 0; + suffix->tr_nexttrans = 0; + suffix->tr_nextstate = x->x_translist; + x->x_translist = suffix; + } + if (trans = getbytes(sizeof(*trans))) + { + trans->tr_value = suffval; + trans->tr_count = count; + trans->tr_suffix = suffix; + trans->tr_nexttrans = prefix->tr_nexttrans; + trans->tr_nextstate = prefix->tr_nextstate; + prefix->tr_count += count; + prefix->tr_nexttrans = trans; + } + if (!x->x_state) /* CHECKED */ + x->x_state = prefix; /* CHECKED */ + } + else loud_error((t_pd *)x, "bad list message format"); /* CHECKED */ +} + +static void prob_silent(t_prob *x) +{ + if (!x->x_silent) + { + loud_incompatible(prob_class, "no 'silent' message in max"); + x->x_silent = 1; + } +} + +static void prob_click(t_prob *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + t_probtrans *state; + char buf[64]; + hammereditor_open(x->x_filehandle, "prob"); + for (state = x->x_translist; state; state = state->tr_nextstate) + { + t_probtrans *trans; + for (trans = state->tr_nexttrans; trans; trans = trans->tr_nexttrans) + { + sprintf(buf, "%d %d %d\n", + state->tr_value, trans->tr_value, trans->tr_count); + hammereditor_append(x->x_filehandle, buf); + } + } +} + +static void prob_free(t_prob *x) +{ + prob_clear(x); + hammerfile_free(x->x_filehandle); +} + +static void *prob_new(void) +{ + t_prob *x = (t_prob *)pd_new(prob_class); + x->x_translist = 0; + x->x_state = 0; + x->x_default = 0; + x->x_embedmode = 0; /* CHECKED */ + x->x_silent = 0; + rand_seed(&x->x_seed, 0); + outlet_new((t_object *)x, &s_float); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, 0, 0); + return (x); +} + +void prob_setup(void) +{ + prob_class = class_new(gensym("prob"), + (t_newmethod)prob_new, + (t_method)prob_free, + sizeof(t_prob), 0, 0); + class_addbang(prob_class, prob_bang); + class_addfloat(prob_class, prob_float); + class_addlist(prob_class, prob_list); + class_addmethod(prob_class, (t_method)prob_embed, + gensym("embed"), A_FLOAT, 0); + class_addmethod(prob_class, (t_method)prob_reset, + gensym("reset"), A_FLOAT, 0); + class_addmethod(prob_class, (t_method)prob_clear, + gensym("clear"), 0); + class_addmethod(prob_class, (t_method)prob_dump, + gensym("dump"), 0); + /* CHECKED: doesn't understand "seed" */ + + /* below are the incompatible extensions... */ + class_addmethod(prob_class, (t_method)prob_silent, + gensym("silent"), 0); + class_addmethod(prob_class, (t_method)prob_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(prob_class, 0); /* LATER embedding (, 1) */ +} diff --git a/cyclone/hammer/pv.c b/cyclone/hammer/pv.c new file mode 100644 index 0000000..235da2c --- /dev/null +++ b/cyclone/hammer/pv.c @@ -0,0 +1,457 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKED (it cannot be emulated): creating [s/r <pv-symbol>] prints + "error:send/receive:<pv-symbol>:already exists" +*/ + +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "common/grow.h" + +#define PV_INISIZE 32 /* LATER rethink */ +#define PV_MAXSIZE 256 + +typedef struct _pvfamily +{ + t_symbol *f_selector; + t_float f_float; + t_symbol *f_symbol; + t_gpointer *f_pointer; + int f_size; /* as allocated */ + int f_natoms; /* as used */ + t_atom *f_message; + t_atom f_messini[PV_INISIZE]; + t_glist *f_glist; /* root glist of a family */ + t_symbol *f_name; + struct _pvfamily *f_next; +} t_pvfamily; + +typedef struct _pvlist +{ + t_pd l_pd; + int l_refcount; + t_symbol *l_name; + t_pvfamily *l_pvlist; +} t_pvlist; + +typedef struct _pv +{ + t_object x_ob; + t_glist *x_glist; + t_symbol *x_name; + t_pvfamily *x_family; +} t_pv; + +static t_class *pv_class; +static t_class *pvlist_class; + +static void pvlist_decrement(t_pvlist *pl) +{ + if (!--pl->l_refcount) + { + pd_unbind(&pl->l_pd, pl->l_name); + pd_free(&pl->l_pd); + } +} + +static t_pvlist *pv_getlist(t_symbol *s, int create) +{ + t_pvlist *pl = (t_pvlist *)pd_findbyclass(s, pvlist_class); + if (pl) + { + if (create) pl->l_refcount++; + } + else + { + if (create) + { + pl = (t_pvlist *)pd_new(pvlist_class); + pl->l_refcount = 1; + pl->l_name = s; + pl->l_pvlist = 0; + pd_bind(&pl->l_pd, s); + } + else bug("pv_getlist"); + } + return (pl); +} + +static t_pvfamily *pv_newfamily(t_pvlist *pvlist) +{ + t_pvfamily *pf = (t_pvfamily *)getbytes(sizeof(*pf)); + pf->f_name = pvlist->l_name; + pf->f_next = pvlist->l_pvlist; + pvlist->l_pvlist = pf; + pf->f_selector = 0; + pf->f_float = 0; + pf->f_symbol = 0; + pf->f_pointer = 0; + pf->f_size = PV_INISIZE; + pf->f_natoms = 0; + pf->f_message = pf->f_messini; + return (pf); +} + +static void pvfamily_free(t_pvfamily *pf) +{ + if (pf->f_message != pf->f_messini) + freebytes(pf->f_message, pf->f_size * sizeof(*pf->f_message)); + freebytes(pf, sizeof(*pf)); +} + +static void pv_update(t_glist *glist, t_pvfamily *pf) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + pv_update((t_glist *)g, pf); + else if (pd_class(&g->g_pd) == pv_class + && ((t_pv *)g)->x_name == pf->f_name) + ((t_pv *)g)->x_family = pf; +} + +static t_pvfamily *pvfamily_reusable; + +static void pv_breakup(t_pvlist *pvlist, t_glist *glist) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + { + if (pd_class(&g->g_pd) == pv_class + && ((t_pv *)g)->x_name == pvlist->l_name) + { + t_pvfamily *pf; + if (!(pf = pvfamily_reusable)) + pf = pv_newfamily(pvlist); + else pvfamily_reusable = 0; + pf->f_glist = glist; + pv_update(glist, pf); + /* LATER keep current value */ + return; + } + } + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + pv_breakup(pvlist, (t_glist *)g); +} + +/* join all families of a 'pvlist' rooted in any subglist of a 'glist' */ +static t_pvfamily *pv_joinup(t_pvlist *pvlist, t_glist *glist) +{ + t_pvfamily *result = 0; + t_pvfamily *pf, *pfprev, *pfnext; + for (pfprev = 0, pf = pvlist->l_pvlist; pf; pfprev = pf, pf = pfnext) + { + t_glist *gl; + pfnext = pf->f_next; + for (gl = pf->f_glist; gl; gl = gl->gl_owner) + { + if (gl == glist) + { + if (result) + { + pvfamily_free(pf); + if (pfprev) + pfprev->f_next = pfnext; + else + pvlist->l_pvlist = pfnext; + pf = pfprev; + } + else result = pf; + break; + } + } + } + return (result); +} + +/* Called normally with either 'create' or 'destroy' set to 1, + but it might be called with both set to 0 for testing. */ +static t_pvfamily *pv_getfamily(t_glist *glist, t_symbol *s, + int create, int destroy) +{ + t_pvlist *pl = pv_getlist(s, create); + if (pl) + { + if (destroy) + { + t_pvfamily *pf, *mypf; + t_glist *gl; + for (mypf = pl->l_pvlist; mypf; mypf = mypf->f_next) + if (mypf->f_glist == glist) + break; + /* mypf is not null iff we are invoked via a [pv] in root */ + /* now check if there is a family rooted in a super-branch */ + for (gl = glist->gl_owner; gl; gl = gl->gl_owner) + { + for (pf = pl->l_pvlist; pf; pf = pf->f_next) + { + if (pf->f_glist == gl) + { + if (mypf) + bug("pv_getfamily 1: %s in %s", + mypf->f_name->s_name, + mypf->f_glist->gl_name->s_name); + else + return (0); + } + } + } + if (mypf) + { + pvfamily_reusable = mypf; + pv_breakup(pl, glist); + if (pvfamily_reusable == mypf) + { + pvfamily_reusable = 0; + if (pl->l_pvlist == mypf) + pl->l_pvlist = mypf->f_next; + else + { + for (pf = pl->l_pvlist; pf; pf = pf->f_next) + { + if (pf->f_next == mypf) + { + pf->f_next = mypf->f_next; + break; + } + } + if (!pf) bug("pv_getfamily 2"); + } + pvfamily_free(mypf); + } + } + else bug("pv_getfamily 3"); + pvlist_decrement(pl); + } + else + { + t_pvfamily *pf; + t_glist *gl; + for (gl = glist; gl; gl = gl->gl_owner) + for (pf = pl->l_pvlist; pf; pf = pf->f_next) + if (pf->f_glist == gl) + return (pf); + if (create) + { + if (!(pf = pv_joinup(pl, glist))) + pf = pv_newfamily(pl); + pf->f_glist = glist; + pv_update(glist, pf); + return (pf); + } + else bug("pv_getfamily 4"); + } + } + else bug("pv_getfamily 5"); + return (0); +} + +static t_pvfamily *pv_checkfamily(t_pv *x) +{ + if (!x->x_family) + { + bug("pv_checkfamily"); + x->x_family = pv_getfamily(x->x_glist, x->x_name, 0, 0); + } + return (x->x_family); +} + +static void pv_bang(t_pv *x) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + t_symbol *s = pf->f_selector; + if (s == &s_bang) + outlet_bang(((t_object *)x)->ob_outlet); + else if (s == &s_float) + outlet_float(((t_object *)x)->ob_outlet, pf->f_float); + else if (s == &s_symbol && pf->f_symbol) + outlet_symbol(((t_object *)x)->ob_outlet, pf->f_symbol); + else if (s == &s_pointer) + { + /* LATER */ + } + else if (s == &s_list) + outlet_list(((t_object *)x)->ob_outlet, + s, pf->f_natoms, pf->f_message); + else if (s) + outlet_anything(((t_object *)x)->ob_outlet, + s, pf->f_natoms, pf->f_message); + } +} + +static void pv_float(t_pv *x, t_float f) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + pf->f_selector = &s_float; + pf->f_float = f; + pf->f_natoms = 0; /* defensive */ + } +} + +static void pv_symbol(t_pv *x, t_symbol *s) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + pf->f_selector = &s_symbol; + pf->f_symbol = s; + pf->f_natoms = 0; /* defensive */ + } +} + +static void pv_pointer(t_pv *x, t_gpointer *gp) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + pf->f_selector = &s_pointer; + pf->f_pointer = gp; + pf->f_natoms = 0; /* defensive */ + } +} + +static void pvfamily_domessage(t_pvfamily *pf, int ac, t_atom *av) +{ + if (ac > pf->f_size) + { + /* LATER consider using PV_MAXSIZE (and warning if exceeded) */ + pf->f_message = grow_nodata(&ac, &pf->f_size, pf->f_message, + PV_INISIZE, pf->f_messini, + sizeof(*pf->f_message)); + } + pf->f_natoms = ac; + memcpy(pf->f_message, av, ac * sizeof(*pf->f_message)); +} + +static void pv_list(t_pv *x, t_symbol *s, int ac, t_atom *av) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + pf->f_selector = &s_list; /* LATER rethink */ + pvfamily_domessage(pf, ac, av); + } +} + +static void pv_anything(t_pv *x, t_symbol *s, int ac, t_atom *av) +{ + t_pvfamily *pf = pv_checkfamily(x); + if (pf) + { + pf->f_selector = s; /* LATER rethink */ + pvfamily_domessage(pf, ac, av); + } +} + +static void pv_objstatus(t_pv *x, t_glist *glist) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + { + if (g == (t_gobj *)x) + post("%x (this object) owning patcher [%s]", + (int)g, glist->gl_name->s_name); + else if (pd_class(&g->g_pd) == pv_class + && ((t_pv *)g)->x_name == x->x_name) + post("%x owning patcher [%s]", (int)g, glist->gl_name->s_name); + } +} + +static void pv_status(t_pv *x) +{ + t_pvlist *pl = pv_getlist(x->x_name, 0); + post("pv status: Tied to %s", x->x_name->s_name); + if (pl) + { + t_pvfamily *pf; + int fcount; + for (pf = pl->l_pvlist, fcount = 1; pf; pf = pf->f_next, fcount++) + { + t_glist *glist = pf->f_glist; + t_gobj *g; + post("Family %d:", fcount); + pv_objstatus(x, glist); + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + pv_objstatus(x, (t_glist *)g); + } + } +} + +static void pv_free(t_pv *x) +{ + pv_getfamily(x->x_glist, x->x_name, 0, 1); +} + +static void *pv_new(t_symbol *s, int ac, t_atom *av) +{ + t_pv *x = 0; + if (ac && av->a_type == A_SYMBOL) + s = av->a_w.w_symbol; + else s = 0; + if (s && s != &s_) + { + t_glist *gl = canvas_getcurrent(); + t_pvfamily *pf = pv_getfamily(gl, s, 1, 0); + x = (t_pv *)pd_new(pv_class); + x->x_glist = gl; + x->x_name = s; + x->x_family = pf; + outlet_new((t_object *)x, &s_float); + if (--ac) + { + av++; + if (av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == &s_symbol) + { + if (ac > 1 && av[1].a_type == A_SYMBOL) + pv_symbol(x, av[1].a_w.w_symbol); + } + /* LATER rethink 'pv <name> bang' (now it is accepted) */ + else pv_anything(x, av->a_w.w_symbol, ac - 1, av + 1); + } + else if (av->a_type == A_FLOAT) + { + if (ac > 1) + pv_list(x, &s_list, ac, av); + else pv_float(x, av->a_w.w_float); + } + } + + } + else + /* CHECKED: "error: missing or bad arguments", + a box is created without inlets and outlets */ + loud_classarg(pv_class); + return (x); +} + +void pv_setup(void) +{ + pv_class = class_new(gensym("pv"), + (t_newmethod)pv_new, + (t_method)pv_free, + sizeof(t_pv), 0, A_GIMME, 0); + class_addbang(pv_class, pv_bang); + class_addfloat(pv_class, pv_float); + class_addsymbol(pv_class, pv_symbol); + class_addpointer(pv_class, pv_pointer); + class_addlist(pv_class, pv_list); + class_addanything(pv_class, pv_anything); + class_addmethod(pv_class, (t_method)pv_status, + gensym("status"), 0); + /* CHECKED: sending bang (or int, list, status, etc.) with '; <pv-symbol>' + "error::doesn't understand bang" (class name is an empty string) */ + pvlist_class = class_new(&s_, 0, 0, + sizeof(t_pvlist), CLASS_PD, 0); +} diff --git a/cyclone/hammer/seq.c b/cyclone/hammer/seq.c new file mode 100644 index 0000000..503b205 --- /dev/null +++ b/cyclone/hammer/seq.c @@ -0,0 +1,825 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKED no sharing of data among seq objects having the same creation arg */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "shared.h" +#include "common/loud.h" +#include "common/grow.h" +#include "common/sq.h" +#include "common/bifi.h" +#include "common/mifi.h" +#include "hammer/file.h" + +#define SEQ_DEBUG + +#define SEQ_INISIZE 256 /* LATER rethink */ +#define SEQ_EOM 255 /* end of message marker, LATER rethink */ + +typedef struct _seqevent +{ + int e_delta; + unsigned char e_bytes[4]; +} t_seqevent; + +typedef struct _seq +{ + t_object x_ob; + t_canvas *x_canvas; + t_symbol *x_defname; + t_hammerfile *x_filehandle; + int x_isplaying; + int x_isrecording; + int x_playhead; + float x_tempo; + double x_prevtime; + unsigned char x_status; + int x_evesize; + int x_expectedsize; + int x_size; /* as allocated */ + int x_nevents; /* as used */ + t_seqevent *x_sequence; + t_seqevent x_seqini[SEQ_INISIZE]; + t_clock *x_clock; + t_outlet *x_bangout; +} t_seq; + +static t_class *seq_class; + +static void seq_doclear(t_seq *x, int dofree) +{ + if (dofree && x->x_sequence != x->x_seqini) + { + freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence)); + x->x_sequence = x->x_seqini; + x->x_size = SEQ_INISIZE; + } + x->x_nevents = 0; +} + +static void seq_complete(t_seq *x) +{ + if (x->x_evesize < x->x_expectedsize) + { + /* CHECKED no warning if no data after status byte requiring data */ + if (x->x_evesize > 1) + post("seq: truncated midi message"); /* CHECKED */ + /* CHECKED nothing stored */ + } + else + { + t_seqevent *ep = &x->x_sequence[x->x_nevents]; + double elapsed = clock_gettimesince(x->x_prevtime); + ep->e_delta = (int)elapsed; + x->x_prevtime = clock_getlogicaltime(); + if (x->x_evesize < 4) + ep->e_bytes[x->x_evesize] = SEQ_EOM; + x->x_nevents++; + if (x->x_nevents >= x->x_size) + { + int nexisting = x->x_size; + /* store-ahead scheme, LATER consider using x_currevent */ + int nrequested = x->x_nevents + 1; +#ifdef SEQ_DEBUG + post("growing..."); +#endif + x->x_sequence = + grow_withdata(&nrequested, &nexisting, + &x->x_size, x->x_sequence, + SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence)); + if (nrequested <= x->x_nevents) + x->x_nevents = 0; + } + } + x->x_evesize = 0; +} + +static void seq_checkstatus(t_seq *x, unsigned char c) +{ + if (x->x_status && x->x_evesize > 1) /* LATER rethink */ + seq_complete(x); + if (c < 192) + x->x_expectedsize = 3; + else if (c < 224) + x->x_expectedsize = 2; + else if (c < 240) + x->x_expectedsize = 3; + else if (c < 248) + { + /* FIXME */ + x->x_expectedsize = -1; + } + else + { + x->x_sequence[x->x_nevents].e_bytes[0] = c; + x->x_evesize = x->x_expectedsize = 1; + seq_complete(x); + return; + } + x->x_status = x->x_sequence[x->x_nevents].e_bytes[0] = c; + x->x_evesize = 1; +} + +static void seq_addbyte(t_seq *x, unsigned char c, int docomplete) +{ + x->x_sequence[x->x_nevents].e_bytes[x->x_evesize++] = c; + if (x->x_evesize == x->x_expectedsize) + { + seq_complete(x); + if (x->x_status) + { + x->x_sequence[x->x_nevents].e_bytes[0] = x->x_status; + x->x_evesize = 1; + } + } + else if (x->x_evesize == 4) + { + if (x->x_status != 240) + bug("seq_addbyte"); + /* CHECKED sysex is broken into 4-byte packets marked with + the actual delta time of last byte received in a packet */ + seq_complete(x); + } + else if (docomplete) seq_complete(x); +} + +static void seq_endofsysex(t_seq *x) +{ + seq_addbyte(x, 247, 1); + x->x_status = 0; +} + +static void seq_stopplayback(t_seq *x) +{ + /* FIXME */ + /* CHECKED "seq: incomplete sysex" at playback stop, 247 added implicitly */ + /* CHECKME resetting controllers, etc. */ + /* CHECKED bang not sent if playback stopped early */ + clock_unset(x->x_clock); + x->x_playhead = 0; + x->x_isplaying = 0; +} + +static void seq_stoprecording(t_seq *x) +{ + if (x->x_status == 240) + { + post("seq: incomplete sysex"); /* CHECKED */ + seq_endofsysex(x); /* CHECKED 247 added implicitly */ + } + else if (x->x_status) + seq_complete(x); + /* CHECKED running status used in recording, but not across recordings */ + x->x_status = 0; + x->x_isrecording = 0; +} + +static void seq_tick(t_seq *x) +{ + if (x->x_isplaying) + { + t_seqevent *ep = &x->x_sequence[x->x_playhead++]; + unsigned char *bp = ep->e_bytes; +nextevent: + outlet_float(((t_object *)x)->ob_outlet, *bp++); + if (*bp != SEQ_EOM) + { + outlet_float(((t_object *)x)->ob_outlet, *bp++); + if (*bp != SEQ_EOM) + { + outlet_float(((t_object *)x)->ob_outlet, *bp++); + if (*bp != SEQ_EOM) + outlet_float(((t_object *)x)->ob_outlet, *bp++); + } + } + if (!x->x_isplaying) /* reentrancy protection */ + return; + if (x->x_playhead < x->x_nevents) + { + ep++; + if (ep->e_delta <= 0) + /* continue output in the same scheduler event, LATER rethink */ + { + x->x_playhead++; + bp = ep->e_bytes; + goto nextevent; + } + else clock_delay(x->x_clock, ep->e_delta); + } + else + { + seq_stopplayback(x); + /* CHECKED bang sent immediately _after_ last byte */ + outlet_bang(x->x_bangout); /* LATER think about reentrancy */ + } + } +} + +/* CHECKED running status not used in playback */ +static void seq_dostart(t_seq *x, float tempo) +{ + if (x->x_isplaying) + { + /* CHECKED tempo change */ + x->x_tempo = tempo; + /* FIXME update the clock */ + } + else + { + if (x->x_isrecording) /* CHECKED 'start' stops recording */ + seq_stoprecording(x); + /* CHECKED bang not sent if a sequence is empty */ + if (x->x_nevents) + { + x->x_tempo = tempo; + x->x_playhead = 0; + x->x_isplaying = 1; + /* playback data never sent within the scheduler event of + a start message (even for the first delta <= 0), LATER rethink */ + clock_delay(x->x_clock, x->x_sequence->e_delta); + } + } +} + +static void seq_bang(t_seq *x) +{ + seq_dostart(x, 1.0); +} + +static void seq_float(t_seq *x, t_float f) +{ + if (x->x_isrecording) + { + /* CHECKED noninteger and out of range silently truncated */ + unsigned char c = (unsigned char)f; + if (c < 128) + { + if (x->x_status) seq_addbyte(x, c, 0); + } + else if (c != 254) /* CHECKED active sensing ignored */ + { + if (x->x_status == 240) + { + if (c == 247) seq_endofsysex(x); + else + { + /* CHECKED rt bytes alike */ + post("seq: unterminated sysex"); /* CHECKED */ + seq_endofsysex(x); /* CHECKED 247 added implicitly */ + seq_checkstatus(x, c); + } + } + else if (c != 247) seq_checkstatus(x, c); + } + } +} + +static void seq_symbol(t_seq *x, t_symbol *s) +{ + loud_nomethod((t_pd *)x, &s_symbol); /* CHECKED */ +} + +static void seq_list(t_seq *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_FLOAT) seq_float(x, av->a_w.w_float); + /* CHECKED anything else/more silently ignored */ +} + +static void seq_record(t_seq *x) +{ + /* CHECKED 'record' resets recording */ + if (x->x_isplaying) /* CHECKED 'record' stops playback */ + seq_stopplayback(x); + seq_doclear(x, 0); + x->x_isrecording = 1; + x->x_prevtime = clock_getlogicaltime(); + x->x_status = 0; + x->x_evesize = 0; + x->x_expectedsize = -1; /* LATER rethink */ +} + +static void seq_append(t_seq *x) +{ + if (x->x_isrecording) + return; /* CHECKME 'append' does not reset recording */ + if (x->x_isplaying) /* CHECKME 'append' stops playback */ + seq_stopplayback(x); + x->x_isrecording = 1; + x->x_prevtime = clock_getlogicaltime(); + x->x_status = 0; + x->x_evesize = 0; + x->x_expectedsize = -1; /* LATER rethink */ +} + +static void seq_stop(t_seq *x) +{ + if (x->x_isplaying) + seq_stopplayback(x); + else if (x->x_isrecording) + seq_stoprecording(x); +} + +static int seq_dogrowing(t_seq *x, int nevents) +{ + if (nevents > x->x_size) + { + int nrequested = nevents; +#ifdef SEQ_DEBUG + post("growing..."); +#endif + x->x_sequence = + grow_nodata(&nrequested, &x->x_size, x->x_sequence, + SEQ_INISIZE, x->x_seqini, sizeof(*x->x_sequence)); + if (nrequested < nevents) + { + x->x_nevents = 0; + return (0); + } + } + x->x_nevents = nevents; + return (1); +} + +static int seq_seekhook(t_squiter *it, int offset) +{ + t_seq *x = (t_seq *)it->i_owner; + post("seek in %d", x->x_nevents); + it->i_nelems = x->x_nevents; + it->i_sequence = x->x_sequence; + if (offset < 0) + offset += it->i_nelems; + if (offset >= 0 && offset < it->i_nelems) + { + it->i_element = (t_seqevent *)it->i_sequence + offset; + it->i_index = offset; + return (1); + } + else return (0); +} + +static void seq_incrhook(t_squiter *it) +{ + ((t_seqevent *)it->i_element)++; + it->i_index++; +} + +/* LATER put seq_mfwrite_doit() functionality here */ +static void seq_getevehook(t_squiter *it, t_mifi_event *mev, int *ret) +{ + *ret = 1; +} + +static void seq_setevehook(t_squiter *it, t_mifi_event *mev, int *ret) +{ + t_seqevent *sev = it->i_element; + sev->e_delta = mev->e_delay; + sev->e_bytes[0] = mev->e_status | mev->e_channel; + sev->e_bytes[1] = mev->e_data[0]; + if (MIFI_ONE_DATABYTE(mev->e_status)) + sev->e_bytes[2] = SEQ_EOM; + else + { + sev->e_bytes[2] = mev->e_data[1]; + sev->e_bytes[3] = SEQ_EOM; + } + *ret = 1; +} + +static t_float seq_gettimhook(t_squiter *it, int *ret) +{ + t_seqevent *sev = it->i_element; + *ret = 1; + return (sev->e_delta); +} + +static void seq_settimhook(t_squiter *it, t_float f, int *ret) +{ + t_seqevent *sev = it->i_element; + sev->e_delta = f; + *ret = 1; +} + +static t_symbol *seq_gettarhook(t_squiter *it, int *ret) +{ + *ret = 1; + return (0); +} + +static void seq_settarhook(t_squiter *it, t_symbol *s, int *ret) +{ + *ret = 1; +} + +static int seq_make_iterator(t_seq *x, t_mifi_stream *stp) +{ + t_squiter *it = squiter_new(stp); + if (it) + { + it->i_owner = x; + it->i_nelems = x->x_nevents; + it->i_sequence = it->i_element = x->x_sequence; + it->i_index = 0; + it->i_hooks[SQUITER_SEEKHOOK] = (t_squiterhook)seq_seekhook; + it->i_hooks[SQUITER_INCRHOOK] = (t_squiterhook)seq_incrhook; + it->i_hooks[SQUITER_GETEVEHOOK] = (t_squiterhook)seq_getevehook; + it->i_hooks[SQUITER_SETEVEHOOK] = (t_squiterhook)seq_setevehook; + it->i_hooks[SQUITER_GETTIMHOOK] = (t_squiterhook)seq_gettimhook; + it->i_hooks[SQUITER_SETTIMHOOK] = (t_squiterhook)seq_settimhook; + it->i_hooks[SQUITER_GETTARHOOK] = (t_squiterhook)seq_gettarhook; + it->i_hooks[SQUITER_SETTARHOOK] = (t_squiterhook)seq_settarhook; + return (1); + } + else return (0); +} + +static t_mifi_stream *seq_makestream(t_seq *x) +{ + t_mifi_stream *stp = 0; + if (stp = mifi_stream_new()) + { + if (seq_make_iterator(x, stp)) + return (stp); + else + mifi_stream_free(stp); + } + return (0); +} + +static int seq_comparehook(const void *e1, const void *e2) +{ + return (((t_seqevent *)e1)->e_delta > ((t_seqevent *)e2)->e_delta ? 1 : -1); +} + +/* FIXME */ +static int seq_mfread(t_seq *x, char *path) +{ + int result = 0; + t_mifi_stream *stp = 0; + if (!(stp = seq_makestream(x)) || + !mifi_read_start(stp, path, "", 0)) + goto readfailed; +#ifdef SEQ_DEBUG + if (stp->s_nframes) + post("midifile (format %d): %d tracks, %d ticks (%d smpte frames)", + stp->s_format, stp->s_hdtracks, stp->s_nticks, stp->s_nframes); + else + post("midifile (format %d): %d tracks, %d ticks per beat", + stp->s_format, stp->s_hdtracks, stp->s_nticks); +#endif + if (mifi_read_analyse(stp) != MIFI_READ_EOF || + !seq_dogrowing(x, stp->s_nevents) || + !mifi_read_restart(stp) || + mifi_read_doit(stp) != MIFI_READ_EOF) + goto readfailed; + squmpi_sort(stp); + qsort(x->x_sequence, stp->s_nevents, sizeof(*x->x_sequence), + seq_comparehook); + sq_fold_time(stp); +#ifdef SEQ_DEBUG + post("finished reading %d events from midifile", stp->s_nevents); +#endif + result = 1; +readfailed: + if (stp) + { + mifi_read_end(stp); + mifi_stream_free(stp); + } + return (result); +} + +/* FIXME */ +static int seq_mfwrite_doit(t_seq *x, t_mifi_stream *stp) +{ + t_mifi_event *mev = stp->s_auxeve; + t_seqevent *sev = x->x_sequence; + int nevents = x->x_nevents; + while (nevents--) + { + unsigned char *bp = sev->e_bytes; + int i; + mev->e_delay = (uint32)(sev->e_delta * stp->s_timecoef); + mev->e_status = *bp & 0xf0; + mev->e_channel = *bp & 0x0f; + /* FIXME sysex continuation */ + for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++) + mev->e_data[i] = *bp; + if (!mifi_write_event(stp, mev)) + return (0); + sev++; + } + return (1); +} + +/* FIXME */ +static int seq_mfwrite(t_seq *x, char *path) +{ + int result = 0; + t_mifi_stream *stp = 0; + if (!(stp = seq_makestream(x))) + goto writefailed; + stp->s_ntracks = 1; + stp->s_hdtracks = 1; + stp->s_format = 0; + if (!mifi_write_start(stp, path, "")) + goto writefailed; + mifi_event_settext(stp->s_auxeve, MIFI_META_TRACKNAME, "seq-track"); + if (!mifi_write_start_track(stp) || + !mifi_write_event(stp, stp->s_auxeve) || + !seq_mfwrite_doit(x, stp) || + !mifi_write_adjust_track(stp, 0)) + goto writefailed; + result = 1; +writefailed: + if (stp) + { + mifi_write_end(stp); + mifi_stream_free(stp); + } + return (result); +} + +/* FIXME */ +/* CHECKED absolute timestamps, semi-terminated, verified */ +static int seq_frombinbuf(t_seq *x, t_binbuf *bb) +{ + int nevents = 0; + int ac = binbuf_getnatom(bb); + t_atom *av = binbuf_getvec(bb); + while (ac--) + if (av++->a_type == A_SEMI) /* FIXME parsing */ + nevents++; + if (nevents) + { + t_seqevent *ep; + float prevtime = 0; + int i = -1; + if (!seq_dogrowing(x, nevents)) + return (0); + nevents = 0; + ac = binbuf_getnatom(bb); + av = binbuf_getvec(bb); + ep = x->x_sequence; + while (ac--) + { + if (av->a_type == A_FLOAT) + { + if (i < 0) + { + ep->e_delta = av->a_w.w_float - prevtime; + prevtime = av->a_w.w_float; + i = 0; + } + else if (i < 4) + ep->e_bytes[i++] = av->a_w.w_float; + /* CHECKME else */ + } + else if (av->a_type == A_SEMI && i > 0) + { + if (i < 4) + ep->e_bytes[i] = SEQ_EOM; + nevents++; + ep++; + i = -1; + } + /* CHECKME else */ + av++; + } + x->x_nevents = nevents; + } + return (nevents); +} + +static void seq_tobinbuf(t_seq *x, t_binbuf *bb) +{ + int nevents = x->x_nevents; + t_seqevent *ep = x->x_sequence; + t_atom at[5]; + float timestamp = 0; + while (nevents--) + { + unsigned char *bp = ep->e_bytes; + int i; + t_atom *ap = at; + timestamp += ep->e_delta; + SETFLOAT(ap, timestamp); /* CHECKED same for sysex continuation */ + ap++; + SETFLOAT(ap, *bp); + for (i = 0, ap++, bp++; i < 3 && *bp != SEQ_EOM; i++, ap++, bp++) + SETFLOAT(ap, *bp); + binbuf_add(bb, i + 2, at); + binbuf_addsemi(bb); + ep++; + } +} + +static void seq_textread(t_seq *x, char *path) +{ + t_binbuf *bb; + bb = binbuf_new(); + if (binbuf_read(bb, path, "", 0)) + { + /* CHECKED no complaint, open dialog presented */ + hammerpanel_open(x->x_filehandle); /* LATER rethink */ + } + else + { + int nlines = seq_frombinbuf(x, bb); + if (nlines < 0) + /* CHECKED "bad MIDI file (truncated)" alert, even if a text file */ + loud_error((t_pd *)x, "bad text file (truncated)"); + else if (nlines == 0) + { + /* CHECKED no complaint, sequence erased, LATER rethink */ + } + } + binbuf_free(bb); +} + +static void seq_textwrite(t_seq *x, char *path) +{ + t_binbuf *bb; + bb = binbuf_new(); + seq_tobinbuf(x, bb); + /* CHECKED empty sequence stored as an empty file */ + if (binbuf_write(bb, path, "", 0)) + { + /* CHECKME complaint and FIXME */ + loud_error((t_pd *)x, "error writing text file"); + } + binbuf_free(bb); +} + +static void seq_doread(t_seq *x, t_symbol *fn, int creation) +{ + char buf[MAXPDSTRING]; + if (x->x_canvas) + canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); + else + { + strncpy(buf, fn->s_name, MAXPDSTRING); + buf[MAXPDSTRING-1] = 0; + } + if (creation) + { + /* loading during object creation -- CHECKED no warning if a file + specified with an arg does not exist, LATER rethink */ + FILE *fp; + char path[MAXPDSTRING]; + sys_bashfilename(buf, path); + if (!(fp = fopen(path, "r"))) + return; + fclose(fp); + } + /* CHECKED all cases: arg or not, message and creation */ + post("seq: reading %s", fn->s_name); + if (!seq_mfread(x, buf)) + seq_textread(x, buf); +} + +static void seq_dowrite(t_seq *x, t_symbol *fn) +{ + char buf[MAXPDSTRING], *dotp; + if (x->x_canvas) + canvas_makefilename(x->x_canvas, fn->s_name, buf, MAXPDSTRING); + else + { + strncpy(buf, fn->s_name, MAXPDSTRING); + buf[MAXPDSTRING-1] = 0; + } + post("seq: writing %s", fn->s_name); /* CHECKED arg or not */ + /* save as text for any extension other then ".mid" */ + if ((dotp = strrchr(fn->s_name, '.')) && strcmp(dotp + 1, "mid")) + seq_textwrite(x, buf); + else /* save as mf for ".mid" or no extension at all, LATER rethink */ + seq_mfwrite(x, buf); +} + +static void seq_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + seq_doread((t_seq *)z, fn, 0); +} + +static void seq_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + seq_dowrite((t_seq *)z, fn); +} + +static void seq_read(t_seq *x, t_symbol *s) +{ + if (s && s != &s_) + seq_doread(x, s, 0); + else /* CHECKED no default */ + hammerpanel_open(x->x_filehandle); +} + +static void seq_write(t_seq *x, t_symbol *s) +{ + if (s && s != &s_) + seq_dowrite(x, s); + else /* CHECKED creation arg is a default */ + hammerpanel_save(x->x_filehandle, + canvas_getdir(x->x_canvas), x->x_defname); +} + +static void seq_print(t_seq *x) +{ + int nevents = x->x_nevents; + startpost("midiseq:"); /* CHECKED */ + if (nevents) + { + t_seqevent *ep = x->x_sequence; + int truncated; + if (nevents > 16) + nevents = 16, truncated = 1; + else + truncated = 0; + while (nevents--) + { + unsigned char *bp = ep->e_bytes; + int i; + if (*bp < 128 || *bp == 247) + /* CHECKED (sysex continuation) */ + startpost("\n(%d)->", ep->e_delta); + else + startpost("\n(%d)", ep->e_delta); + /* CHECKED space-separated, no semi */ + postfloat((float)*bp); + for (i = 0, bp++; i < 3 && *bp != SEQ_EOM; i++, bp++) + postfloat((float)*bp); + ep++; + } + endpost(); + if (truncated) post("..."); /* CHECKED */ + } + else post(" no sequence"); /* CHECKED */ +} + +static void seq_free(t_seq *x) +{ + if (x->x_clock) clock_free(x->x_clock); + hammerfile_free(x->x_filehandle); + if (x->x_sequence != x->x_seqini) + freebytes(x->x_sequence, x->x_size * sizeof(*x->x_sequence)); +} + +static void *seq_new(t_symbol *s) +{ + t_seq *x = (t_seq *)pd_new(seq_class); + static int warned = 0; + if (!warned) + { + loud_warning((t_pd *)x, "seq is not ready yet"); + warned = 1; + } + x->x_canvas = canvas_getcurrent(); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, + seq_readhook, seq_writehook, 0); + x->x_prevtime = 0; + x->x_size = SEQ_INISIZE; + x->x_nevents = 0; + x->x_sequence = x->x_seqini; + outlet_new((t_object *)x, &s_anything); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + if (s && s != &s_) + { + x->x_defname = s; /* CHECKME if 'read' changes this */ + seq_doread(x, s, 1); + } + else x->x_defname = &s_; + x->x_clock = clock_new(x, (t_method)seq_tick); + return (x); +} + +void seq_setup(void) +{ + seq_class = class_new(gensym("seq"), + (t_newmethod)seq_new, + (t_method)seq_free, + sizeof(t_seq), 0, + A_DEFSYM, 0); + class_addbang(seq_class, seq_bang); + class_addfloat(seq_class, seq_float); + /* CHECKED symbol rejected */ + class_addsymbol(seq_class, seq_symbol); + /* CHECKED 1st atom of a list accepted if a float, ignored if a symbol */ + class_addlist(seq_class, seq_list); + class_addmethod(seq_class, (t_method)seq_record, + gensym("record"), 0); + class_addmethod(seq_class, (t_method)seq_append, + gensym("append"), 0); + class_addmethod(seq_class, (t_method)seq_stop, + gensym("stop"), 0); + class_addmethod(seq_class, (t_method)seq_read, + gensym("read"), A_DEFSYM, 0); + class_addmethod(seq_class, (t_method)seq_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(seq_class, (t_method)seq_print, + gensym("print"), 0); + hammerfile_setup(seq_class, 0); +} diff --git a/cyclone/hammer/sinh.c b/cyclone/hammer/sinh.c new file mode 100644 index 0000000..93fb6fa --- /dev/null +++ b/cyclone/hammer/sinh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sinhf sinh +#endif + +typedef struct _sinh +{ + t_object x_ob; + float x_value; +} t_sinh; + +static t_class *sinh_class; + +static void sinh_bang(t_sinh *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void sinh_float(t_sinh *x, t_float f) +{ + /* CHECKME large values */ + outlet_float(((t_object *)x)->ob_outlet, x->x_value = sinhf(f)); +} + +static void *sinh_new(t_floatarg f) +{ + t_sinh *x = (t_sinh *)pd_new(sinh_class); + /* CHECKME large values */ + x->x_value = sinhf(f); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void sinh_setup(void) +{ + sinh_class = class_new(gensym("sinh"), + (t_newmethod)sinh_new, 0, + sizeof(t_sinh), 0, A_DEFFLOAT, 0); + class_addbang(sinh_class, sinh_bang); + class_addfloat(sinh_class, sinh_float); +} diff --git a/cyclone/hammer/speedlim.c b/cyclone/hammer/speedlim.c new file mode 100644 index 0000000..3cad0f7 --- /dev/null +++ b/cyclone/hammer/speedlim.c @@ -0,0 +1,173 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER 'clock' method */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define SPEEDLIM_INISIZE 32 /* LATER rethink */ +#define SPEEDLIM_MAXSIZE 256 /* not used */ + +typedef struct _speedlim +{ + t_object x_ob; + int x_open; + t_float x_delta; + t_symbol *x_selector; + t_float x_float; + t_symbol *x_symbol; + t_gpointer *x_pointer; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + t_atom *x_message; + t_atom x_messini[SPEEDLIM_INISIZE]; + int x_entered; + t_clock *x_clock; +} t_speedlim; + +static t_class *speedlim_class; + +static void speedlim_dooutput(t_speedlim *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_open = 0; /* so there will be no reentrant calls of dooutput */ + x->x_entered = 1; /* this prevents a message from being overridden */ + clock_unset(x->x_clock); + if (s == &s_bang) + outlet_bang(((t_object *)x)->ob_outlet); + else if (s == &s_float) + outlet_float(((t_object *)x)->ob_outlet, x->x_float); + else if (s == &s_symbol && x->x_symbol) + { + /* if x_symbol is null, then symbol &s_ is passed + by outlet_anything() -> typedmess() */ + outlet_symbol(((t_object *)x)->ob_outlet, x->x_symbol); + x->x_symbol = 0; + } + else if (s == &s_pointer && x->x_pointer) + { + /* LATER */ + x->x_pointer = 0; + } + else if (s == &s_list) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else if (s) + outlet_anything(((t_object *)x)->ob_outlet, s, ac, av); + x->x_selector = 0; + x->x_natoms = 0; + if (x->x_delta > 0) + clock_delay(x->x_clock, x->x_delta); + else + x->x_open = 1; + x->x_entered = 0; +} + +static void speedlim_tick(t_speedlim *x) +{ + if (x->x_selector) + speedlim_dooutput(x, x->x_selector, x->x_natoms, x->x_message); + else + x->x_open = 1; +} + +static void speedlim_anything(t_speedlim *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_open) + speedlim_dooutput(x, s, ac, av); + else if (s && s != &s_ && !x->x_entered) + { + if (ac > x->x_size) + /* MAXSIZE not used, not even a warning... + LATER consider clipping */ + x->x_message = grow_nodata(&ac, &x->x_size, x->x_message, + SPEEDLIM_INISIZE, x->x_messini, + sizeof(*x->x_message)); + x->x_selector = s; + x->x_natoms = ac; + if (ac) + memcpy(x->x_message, av, ac * sizeof(*x->x_message)); + } +} + +static void speedlim_bang(t_speedlim *x) +{ + x->x_selector = &s_bang; + speedlim_anything(x, x->x_selector, 0, 0); +} + +static void speedlim_float(t_speedlim *x, t_float f) +{ + x->x_selector = &s_float; + x->x_float = f; + speedlim_anything(x, x->x_selector, 0, 0); +} + +static void speedlim_symbol(t_speedlim *x, t_symbol *s) +{ + x->x_selector = &s_symbol; + x->x_symbol = s; + speedlim_anything(x, x->x_selector, 0, 0); +} + +/* LATER gpointer */ + +static void speedlim_list(t_speedlim *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_selector = &s_list; + speedlim_anything(x, x->x_selector, ac, av); +} + +static void speedlim_ft1(t_speedlim *x, t_floatarg f) +{ + if (f < 0) + f = 0; /* redundant (and CHECKED) */ + x->x_delta = f; + /* CHECKED: no rearming -- + if clock is set, then new delta value is not used until next tick */ +} + +static void speedlim_free(t_speedlim *x) +{ + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); + if (x->x_clock) + clock_free(x->x_clock); +} + +static void *speedlim_new(t_floatarg f) +{ + t_speedlim *x = (t_speedlim *)pd_new(speedlim_class); + x->x_open = 1; /* CHECKED */ + x->x_delta = 0; + x->x_selector = 0; + x->x_float = 0; + x->x_symbol = 0; + x->x_pointer = 0; + x->x_size = SPEEDLIM_INISIZE; + x->x_natoms = 0; + x->x_message = x->x_messini; + x->x_entered = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_anything); + x->x_clock = clock_new(x, (t_method)speedlim_tick); + speedlim_ft1(x, f); + return (x); +} + +void speedlim_setup(void) +{ + speedlim_class = class_new(gensym("speedlim"), + (t_newmethod)speedlim_new, + (t_method)speedlim_free, + sizeof(t_speedlim), 0, + A_DEFFLOAT, 0); + class_addbang(speedlim_class, speedlim_bang); + class_addfloat(speedlim_class, speedlim_float); + class_addsymbol(speedlim_class, speedlim_symbol); + class_addlist(speedlim_class, speedlim_list); + class_addanything(speedlim_class, speedlim_anything); + class_addmethod(speedlim_class, (t_method)speedlim_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/spell.c b/cyclone/hammer/spell.c new file mode 100644 index 0000000..f9a32d6 --- /dev/null +++ b/cyclone/hammer/spell.c @@ -0,0 +1,149 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "common/loud.h" + +typedef struct _spell +{ + t_object x_ob; + int x_minsize; + int x_padchar; /* actually, any nonnegative integer (CHECKED) */ +} t_spell; + +static t_class *spell_class; + +static void spell_fill(t_spell *x, int cnt) +{ + for (; cnt < x->x_minsize; cnt++) + outlet_float(((t_object *)x)->ob_outlet, x->x_padchar); +} + +/* CHECKED: chars are spelled as signed */ +static int spell_out(t_spell *x, char *ptr, int flush) +{ + int cnt = 0; + while (*ptr) + outlet_float(((t_object *)x)->ob_outlet, *ptr++), cnt++; + if (flush) + { + spell_fill(x, cnt); + return (0); + } + return (cnt); +} + +static void spell_bang(t_spell *x) +{ + /* need to somehow override a default bang-to-empty-list conversion... */ + loud_nomethod((t_pd *)x, &s_bang); /* CHECKED */ +} + +static void spell_float(t_spell *x, t_float f) +{ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) /* CHECKED */ + { + char buf[16]; + sprintf(buf, "%d", i); /* CHECKED (negative numbers) */ + spell_out(x, buf, 1); + } +} + +/* CHECKED: 'symbol' selector is not spelled! */ +static void spell_symbol(t_spell *x, t_symbol *s) +{ + spell_out(x, s->s_name, 1); +} + +static void spell_list(t_spell *x, t_symbol *s, int ac, t_atom *av) +{ + int cnt = 0; + int addsep = 0; + while (ac--) + { + if (addsep) + { + outlet_float(((t_object *)x)->ob_outlet, x->x_padchar); + cnt++; + } + else addsep = 1; + if (av->a_type == A_FLOAT) + { + int i; + /* CHECKME */ + if (loud_checkint((t_pd *)x, av->a_w.w_float, &i, &s_list)) + { + char buf[16]; + sprintf(buf, "%d", i); /* CHECKED (negative numbers) */ + cnt += spell_out(x, buf, 0); + } + /* CHECKED: floats as empty strings (separator is added) */ + } + /* CHECKED: symbols as empty strings (separator is added) */ + av++; + } + if (cnt) /* CHECKED: empty list is silently ignored */ + spell_fill(x, cnt); +} + +static void spell_anything(t_spell *x, t_symbol *s, int ac, t_atom *av) +{ + int cnt = 0; + int addsep = 0; + if (s) + { + cnt += spell_out(x, s->s_name, 0); + addsep = 1; + } + while (ac--) + { + if (addsep) + { + outlet_float(((t_object *)x)->ob_outlet, x->x_padchar); + cnt++; + } + else addsep = 1; + if (av->a_type == A_FLOAT) + { + int i; + /* CHECKME */ + if (loud_checkint((t_pd *)x, av->a_w.w_float, &i, &s_list)) + { + char buf[16]; + sprintf(buf, "%d", i); /* CHECKED (negative numbers) */ + cnt += spell_out(x, buf, 0); + } + /* CHECKED: floats as empty strings (separator is added) */ + } + else if (av->a_type == A_SYMBOL && av->a_w.w_symbol) + cnt += spell_out(x, av->a_w.w_symbol->s_name, 0); + av++; + } + if (cnt) /* CHECKED: empty list is silently ignored */ + spell_fill(x, cnt); +} + +static void *spell_new(t_floatarg f1, t_floatarg f2) +{ + t_spell *x = (t_spell *)pd_new(spell_class); + int i2 = (int)f2; /* CHECKED */ + x->x_minsize = (f1 > 0 ? (int)f1 : 0); + x->x_padchar = (i2 < 0 ? 0 : (i2 > 0 ? i2 : ' ')); /* CHECKED */ + outlet_new((t_object *)x, &s_float); + return (x); +} + +void spell_setup(void) +{ + spell_class = class_new(gensym("spell"), + (t_newmethod)spell_new, 0, + sizeof(t_spell), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(spell_class, spell_bang); + class_addfloat(spell_class, spell_float); + class_addsymbol(spell_class, spell_symbol); + class_addlist(spell_class, spell_list); + class_addanything(spell_class, spell_anything); +} diff --git a/cyclone/hammer/split.c b/cyclone/hammer/split.c new file mode 100644 index 0000000..2865f66 --- /dev/null +++ b/cyclone/hammer/split.c @@ -0,0 +1,64 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +/* CHECKED: + 'list <symbol>' silently ignored (LATER remove a warning) + '<number> <symbol>' as '<number>' (LATER remove a warning) + LATER more compatibility checks are needed... + LATER sort out float/int dilemmas +*/ + +typedef struct _split +{ + t_object x_ob; + int x_floatmode; + t_float x_min; + t_float x_max; + t_outlet *x_out2; +} t_split; + +static t_class *split_class; + +static void split_float(t_split *x, t_float f) +{ + if (x->x_floatmode) + { + if (f >= x->x_min && f <= x->x_max) + outlet_float(((t_object *)x)->ob_outlet, f); + else outlet_float(x->x_out2, f); + } + else + { + /* CHECKED: no pre-truncation */ + if (f >= x->x_min && f <= x->x_max) + outlet_float(((t_object *)x)->ob_outlet, (int)f); + else outlet_float(x->x_out2, (int)f); + } +} + +static void *split_new(t_floatarg f1, t_floatarg f2) +{ + t_split *x = (t_split *)pd_new(split_class); + x->x_floatmode = (f1 != (int)f1); + /* CHECKED: defaults are [0..0] and [0..f1] (for positive f1) or [f1..0] */ + if (f1 < f2) /* CHECKED */ + x->x_min = f1, x->x_max = f2; + else + x->x_min = f2, x->x_max = f1; + floatinlet_new((t_object *)x, &x->x_min); + floatinlet_new((t_object *)x, &x->x_max); + outlet_new((t_object *)x, &s_float); + x->x_out2 = outlet_new((t_object *)x, &s_float); + return (x); +} + +void split_setup(void) +{ + split_class = class_new(gensym("split"), + (t_newmethod)split_new, 0, + sizeof(t_split), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(split_class, split_float); +} diff --git a/cyclone/hammer/spray.c b/cyclone/hammer/spray.c new file mode 100644 index 0000000..8aa0556 --- /dev/null +++ b/cyclone/hammer/spray.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define SPRAY_MINOUTS 1 +/* CHECKED: no upper limit */ +#define SPRAY_DEFOUTS 2 + +typedef struct _spray +{ + t_object x_ob; + int x_offset; + int x_nouts; + t_outlet **x_outs; +} t_spray; + +static t_class *spray_class; + +static void spray_float(t_spray *x, t_float f) +{ + /* CHECKED: floats ignored (LATER rethink), ints loudly rejected */ + if (f == (int)f) loud_error((t_pd *)x, "requires list"); +} + +/* LATER decide, whether float in first atom is to be truncated, + or causing a list to be ignored as in max (CHECKED) */ +static void spray_list(t_spray *x, t_symbol *s, int ac, t_atom *av) +{ + int ndx; + if (ac >= 2 && av->a_type == A_FLOAT + /* CHECKED: lists with negative effective ndx are ignored */ + && (ndx = (int)av->a_w.w_float - x->x_offset) >= 0 + && ndx < x->x_nouts) + { + /* CHECKED: ignored atoms (symbols and floats) are counted */ + /* CHECKED: we must spray in right-to-left order */ + t_atom *argp; + t_outlet **outp; + int last = ac - 1 + ndx; /* ndx of last outlet filled (first is 1) */ + if (last > x->x_nouts) + { + argp = av + 1 + x->x_nouts - ndx; + outp = x->x_outs + x->x_nouts; + } + else + { + argp = av + ac; + outp = x->x_outs + last; + } + /* argp/outp now point to one after the first atom/outlet to deliver */ + for (argp--, outp--; argp > av; argp--, outp--) + if (argp->a_type == A_FLOAT) + outlet_float(*outp, argp->a_w.w_float); + } +} + +static void spray_free(t_spray *x) +{ + if (x->x_outs) + freebytes(x->x_outs, x->x_nouts * sizeof(*x->x_outs)); +} + +static void *spray_new(t_floatarg f1, t_floatarg f2) +{ + t_spray *x; + int i, nouts = (int)f1; + t_outlet **outs; + if (nouts < SPRAY_MINOUTS) + nouts = SPRAY_DEFOUTS; + if (!(outs = (t_outlet **)getbytes(nouts * sizeof(*outs)))) + return (0); + x = (t_spray *)pd_new(spray_class); + x->x_nouts = nouts; + x->x_outs = outs; + x->x_offset = (int)f2; + for (i = 0; i < nouts; i++) + x->x_outs[i] = outlet_new((t_object *)x, &s_float); + return (x); +} + +void spray_setup(void) +{ + spray_class = class_new(gensym("spray"), + (t_newmethod)spray_new, + (t_method)spray_free, + sizeof(t_spray), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + /* CHECKED: bang, symbol, anything -- ``doesn't understand'' */ + class_addfloat(spray_class, spray_float); + class_addlist(spray_class, spray_list); +} diff --git a/cyclone/hammer/sprintf.c b/cyclone/hammer/sprintf.c new file mode 100644 index 0000000..aebfed3 --- /dev/null +++ b/cyclone/hammer/sprintf.c @@ -0,0 +1,634 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME empty string as a default for %s */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" + +#define SPRINTF_DEBUG 0 + +/* Pattern types. These are the parsing routine's return values. + If returned value is >= SPRINTF_MINSLOTTYPE, then another slot + is created (i.e. an inlet, and a proxy handling it). */ +#define SPRINTF_UNSUPPORTED 0 +#define SPRINTF_LITERAL 1 +#define SPRINTF_MINSLOTTYPE 2 +#define SPRINTF_INT 2 +#define SPRINTF_FLOAT 3 +#define SPRINTF_CHAR 4 +#define SPRINTF_STRING 5 + +/* Numbers: assuming max 62 digits preceding a decimal point in any + fixed-point representation of a t_float (39 in my system) + -- need to be sure, that using max precision would never produce + a representation longer than max width. If this is so, then no number + representation would exceed max width (presumably...). + Strings: for the time being, any string longer than max width would + be truncated (somehow compatible with Str256, but LATER warn-and-allow). */ +/* LATER rethink it all */ +#define SPRINTF_MAXPRECISION 192 +#define SPRINTF_MAXWIDTH 256 + +typedef struct _sprintf +{ + t_object x_ob; + int x_nslots; + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; + int x_fsize; /* as allocated (i.e. including a terminating 0) */ + char *x_fstring; +} t_sprintf; + +typedef struct _sprintf_proxy +{ + t_object p_ob; + t_sprintf *p_master; + int p_id; + int p_type; /* a value #defined above */ + char *p_pattern; + char *p_pattend; + t_atom p_atom; /* current input */ + int p_size; /* also an input validation flag */ +} t_sprintf_proxy; + +static t_class *sprintf_class; +static t_class *sprintf_proxy_class; + +/* CHECKED: 'symout' argument has no special meaning in max4.07, + LATER investigate */ + +/* LATER use snprintf, if it is available on other systems (should be...) */ +static void sprintf_proxy_checkit(t_sprintf_proxy *x, char *buf, int checkin) +{ + int result = 0; + char *pattend = x->p_pattend; + if (pattend) + { + char tmp = *pattend; + *pattend = 0; + if (x->p_atom.a_type == A_FLOAT) + { + t_float f = x->p_atom.a_w.w_float; + if (x->p_type == SPRINTF_INT) + /* CHECKME large/negative values */ + result = sprintf(buf, x->p_pattern, (int)f); + else if (x->p_type == SPRINTF_FLOAT) + result = sprintf(buf, x->p_pattern, f); + else if (x->p_type == SPRINTF_CHAR) + /* CHECKED: if 0 is input into a %c-slot, the whole output + string is null-terminated */ + /* CHECKED: float into a %c-slot is truncated, + but CHECKME large/negative values */ + result = sprintf(buf, x->p_pattern, (unsigned char)f); + else if (x->p_type == SPRINTF_STRING) + { + /* CHECKED: any number input into a %s-slot is ok */ + char tmp[64]; /* LATER rethink */ + sprintf(tmp, "%g", f); + result = sprintf(buf, x->p_pattern, tmp); + } + else /* LATER consider calling it a bug(), rather than error? */ + loud_error((t_pd *)x->p_master, + "can't convert float to type of argument %d", + x->p_id + 1); + } + else if (x->p_atom.a_type == A_SYMBOL) + { + t_symbol *s = x->p_atom.a_w.w_symbol; + if (x->p_type == SPRINTF_STRING) + { + if (strlen(s->s_name) > SPRINTF_MAXWIDTH) + { + strncpy(buf, s->s_name, SPRINTF_MAXWIDTH); + buf[SPRINTF_MAXWIDTH] = 0; + result = SPRINTF_MAXWIDTH; + } + else result = sprintf(buf, x->p_pattern, s->s_name); + } + else /* CHECKED */ + loud_error((t_pd *)x->p_master, + "can't convert symbol to type of argument %d", + x->p_id + 1); + } + *pattend = tmp; + } + else bug("sprintf_proxy_checkit"); + if (result > 0) + { +#if SPRINTF_DEBUG + if (checkin) post("[%d in \"%s\"]", result, buf); +#endif + x->p_size = result; + } + else + { +#if SPRINTF_DEBUG + if (checkin) post("checkit failed"); +#endif + x->p_size = 0; + } +} + +static void sprintf_dooutput(t_sprintf *x) +{ + int i, outsize; + char *outstring; + outsize = x->x_fsize; /* this is strlen() + 1 */ + /* LATER consider subtracting format pattern sizes */ + for (i = 0; i < x->x_nslots; i++) + { + t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; + if (y->p_size) + outsize += y->p_size; + else + { + /* slot i has received an invalid input -- CHECKME if this + condition blocks all subsequent output requests? */ + return; + } + } + if (outsize > 0 && (outstring = getbytes(outsize))) + { + char *inp = x->x_fstring; + char *outp = outstring; + for (i = 0; i < x->x_nslots; i++) + { + t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; + int len = y->p_pattern - inp; + if (len > 0) + { + strncpy(outp, inp, len); + outp += len; + } + sprintf_proxy_checkit(y, outp, 0); + outp += y->p_size; /* p_size is never negative */ + inp = y->p_pattend; + } + strcpy(outp, inp); + + outp = outstring; + while (*outp == ' ' || *outp == '\t' + || *outp == '\n' || *outp == '\r') outp++; + if (*outp) + { + t_binbuf *bb = binbuf_new(); + int ac; + t_atom *av; + binbuf_text(bb, outp, strlen(outp)); + ac = binbuf_getnatom(bb); + av = binbuf_getvec(bb); + if (ac) + { + if (av->a_type == A_SYMBOL) + outlet_anything(((t_object *)x)->ob_outlet, + av->a_w.w_symbol, ac - 1, av + 1); + else if (av->a_type == A_FLOAT) + { + if (ac > 1) + outlet_list(((t_object *)x)->ob_outlet, + &s_list, ac, av); + else + outlet_float(((t_object *)x)->ob_outlet, + av->a_w.w_float); + } + } + binbuf_free(bb); + } + freebytes(outstring, outsize); + } +} + +static void sprintf_proxy_bang(t_sprintf_proxy *x) +{ + sprintf_dooutput(x->p_master); /* CHECKED (in any inlet) */ +} + +static void sprintf_proxy_float(t_sprintf_proxy *x, t_float f) +{ + char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ + SETFLOAT(&x->p_atom, f); + sprintf_proxy_checkit(x, buf, 1); + if (x->p_id == 0 && x->p_size) + sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */ +} + +static void sprintf_proxy_symbol(t_sprintf_proxy *x, t_symbol *s) +{ + char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ + if (s && *s->s_name) + SETSYMBOL(&x->p_atom, s); + else + SETFLOAT(&x->p_atom, 0); + sprintf_proxy_checkit(x, buf, 1); + if (x->p_id == 0 && x->p_size) + sprintf_dooutput(x->p_master); /* CHECKED: only first inlet */ +} + +static void sprintf_dolist(t_sprintf *x, + t_symbol *s, int ac, t_atom *av, int startid) +{ + int cnt = x->x_nslots - startid; + if (ac > cnt) + ac = cnt; + if (ac-- > 0) + { + int id; + for (id = startid + ac, av += ac; id >= startid; id--, av--) + { + if (av->a_type == A_FLOAT) + sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[id], + av->a_w.w_float); + else if (av->a_type == A_SYMBOL) + sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[id], + av->a_w.w_symbol); + } + } +} + +static void sprintf_doanything(t_sprintf *x, + t_symbol *s, int ac, t_atom *av, int startid) +{ + if (s && s != &s_) + { + sprintf_dolist(x, 0, ac, av, startid + 1); + sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[startid], s); + } + else sprintf_dolist(x, 0, ac, av, startid); +} + +static void sprintf_proxy_list(t_sprintf_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + sprintf_dolist(x->p_master, s, ac, av, x->p_id); +} + +static void sprintf_proxy_anything(t_sprintf_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + sprintf_doanything(x->p_master, s, ac, av, x->p_id); +} + +static void sprintf_bang(t_sprintf *x) +{ + if (x->x_nslots) + sprintf_proxy_bang((t_sprintf_proxy *)x->x_proxies[0]); +} + +static void sprintf_float(t_sprintf *x, t_float f) +{ + if (x->x_nslots) + sprintf_proxy_float((t_sprintf_proxy *)x->x_proxies[0], f); +} + +static void sprintf_symbol(t_sprintf *x, t_symbol *s) +{ + if (x->x_nslots) + sprintf_proxy_symbol((t_sprintf_proxy *)x->x_proxies[0], s); +} + +static void sprintf_list(t_sprintf *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_nslots) + sprintf_dolist(x, s, ac, av, 0); +} + +static void sprintf_anything(t_sprintf *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_nslots) + sprintf_doanything(x, s, ac, av, 0); +} + +/* adjusted binbuf_gettext(), LATER do it right */ +static char *hammer_gettext(int ac, t_atom *av, int *sizep) +{ + char *buf = getbytes(1); + int size = 1; + char atomtext[MAXPDSTRING]; + while (ac--) + { + char *newbuf; + int newsize; + if (buf[size-1] == 0 || av->a_type == A_SEMI || av->a_type == A_COMMA) + size--; + atom_string(av, atomtext, MAXPDSTRING); + newsize = size + strlen(atomtext) + 1; + if (!(newbuf = resizebytes(buf, size, newsize))) + { + *sizep = 1; + return (getbytes(1)); + } + buf = newbuf; + strcpy(buf + size, atomtext); + size = newsize; + buf[size-1] = ' '; + av++; + } + buf[size-1] = 0; + *sizep = size; + return (buf); +} + +/* Called twice: 1st pass (with x == 0) is used for counting valid patterns; + 2nd pass (after object allocation) -- for initializing the proxies. + If there is a "%%" pattern, then the buffer is shrinked in the second pass + (LATER rethink). */ +static int sprintf_parsepattern(t_sprintf *x, char **patternp) +{ + int type = SPRINTF_UNSUPPORTED; + char errstring[MAXPDSTRING]; + char *ptr; + char modifier = 0; + int width = 0; + int precision = 0; + int *numfield = &width; + int dotseen = 0; + *errstring = 0; + for (ptr = *patternp; *ptr; ptr++) + { + if (*ptr >= '0' && *ptr <= '9') + { + if (!numfield) + { + if (x) sprintf(errstring, "extra number field"); + break; + } + *numfield = 10 * *numfield + *ptr - '0'; + if (dotseen) + { + if (precision > SPRINTF_MAXPRECISION) + { + if (x) sprintf(errstring, "precision field too large"); + break; + } + } + else + { + if (width > SPRINTF_MAXWIDTH) + { + if (x) sprintf(errstring, "width field too large"); + break; + } + } + continue; + } + if (*numfield) + numfield = 0; + + if (strchr("diouxX", *ptr)) + { + type = SPRINTF_INT; + break; + } + else if (strchr("aAeEfgG", *ptr)) + { + if (modifier) + { + if (x) sprintf(errstring, + "\'%c\' modifier not supported", modifier); + break; + } + type = SPRINTF_FLOAT; + break; + } + else if (strchr("c", *ptr)) + { + if (modifier) + { + if (x) sprintf(errstring, + "\'%c\' modifier not supported", modifier); + break; + } + type = SPRINTF_CHAR; + break; + } + else if (strchr("s", *ptr)) + { + if (modifier) + { + if (x) sprintf(errstring, + "\'%c\' modifier not supported", modifier); + break; + } + type = SPRINTF_STRING; + break; + } + else if (*ptr == '%') + { + type = SPRINTF_LITERAL; + if (x) + { /* buffer-shrinking hack, LATER rethink */ + char *p1 = ptr, *p2 = ptr + 1; + do + *p1++ = *p2; + while (*p2++); + ptr--; + } + break; + } + else if (strchr("CSnm", *ptr)) + { + if (x) sprintf(errstring, "\'%c\' type not supported", *ptr); + break; + } + else if (strchr("l", *ptr)) + { + if (modifier) + { + if (x) sprintf(errstring, "only single modifier is supported"); + break; + } + modifier = *ptr; + } + else if (strchr("hjLqtzZ", *ptr)) + { + if (x) sprintf(errstring, "\'%c\' modifier not supported", *ptr); + break; + } + else if (*ptr == '.') + { + if (dotseen) + { + if (x) sprintf(errstring, "multiple dots"); + break; + } + numfield = &precision; + dotseen = 1; + } + else if (*ptr == '$') + { + if (x) sprintf(errstring, "parameter number field not supported"); + break; + } + else if (*ptr == '*') + { + if (x) sprintf(errstring, "%s parameter not supported", + (dotseen ? "precision" : "width")); + break; + } + else if (!strchr("-+ #\'", *ptr)) + { + if (x) sprintf(errstring, + "\'%c\' format character not supported", *ptr); + break; + } + } + if (*ptr) + ptr++; /* LATER rethink */ + else + if (x) sprintf(errstring, "type not specified"); + if (x && type == SPRINTF_UNSUPPORTED) + { + if (*errstring) + loud_error((t_pd *)x, "slot skipped (%s %s)", + errstring, "in a format pattern"); + else + loud_error((t_pd *)x, "slot skipped"); + } + *patternp = ptr; + return (type); +} + +static void sprintf_free(t_sprintf *x) +{ + if (x->x_proxies) + { + int i = x->x_nslots; + while (i--) + { + t_sprintf_proxy *y = (t_sprintf_proxy *)x->x_proxies[i]; + pd_free((t_pd *)y); + } + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } + if (x->x_fstring) + freebytes(x->x_fstring, x->x_fsize); +} + +static void *sprintf_new(t_symbol *s, int ac, t_atom *av) +{ + t_sprintf *x; + int fsize; + char *fstring; + char *p1, *p2; + int i, nslots, nproxies = 0; + t_pd **proxies; + fstring = hammer_gettext(ac, av, &fsize); + p1 = fstring; + while (p2 = strchr(p1, '%')) + { + int type; + p1 = p2 + 1; + type = sprintf_parsepattern(0, &p1); + if (type >= SPRINTF_MINSLOTTYPE) + nproxies++; + } + if (!nproxies) + { + /* CHECKED: an object without arguments, if created in the editor, + has no inlets/outlets, but it would have one inlet (no outlets) + upon loading. Error message is printed in either case. */ + x = (t_sprintf *)pd_new(sprintf_class); + x->x_nslots = 0; + x->x_nproxies = 0; + x->x_proxies = 0; + x->x_fsize = fsize; + x->x_fstring = fstring; + p1 = fstring; + while (p2 = strchr(p1, '%')) + { + p1 = p2 + 1; + sprintf_parsepattern(x, &p1); + } + loud_error((t_pd *)x, + "an object created without valid format patterns..."); + return (x); + } +#if SPRINTF_DEBUG + post("%d slots:", nproxies); +#endif + /* CHECKED: max creates as many inlets, as there are %-signs, no matter + if they are valid, or not -- if not, it prints ``can't convert'' errors + for any input... */ + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + { + freebytes(fstring, fsize); + return (0); + } + for (nslots = 0; nslots < nproxies; nslots++) + if (!(proxies[nslots] = pd_new(sprintf_proxy_class))) break; + if (!nslots) + { + freebytes(fstring, fsize); + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_sprintf *)pd_new(sprintf_class); + x->x_nslots = nslots; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + x->x_fsize = fsize; + x->x_fstring = fstring; + p1 = fstring; + i = 0; + while (p2 = strchr(p1, '%')) + { + int type; + p1 = p2 + 1; + type = sprintf_parsepattern(x, &p1); + if (type >= SPRINTF_MINSLOTTYPE) + { +#if SPRINTF_DEBUG + char tmp = *++p1; + *p1 = 0; + poststring(p2); + endpost(); + *p1 = tmp; +#endif + if (i < nslots) + { + char buf[SPRINTF_MAXWIDTH + 1]; /* LATER rethink */ + t_sprintf_proxy *y = (t_sprintf_proxy *)proxies[i]; + y->p_master = x; + y->p_id = i; + y->p_type = type; + y->p_pattern = p2; + y->p_pattend = p1; + SETFLOAT(&y->p_atom, 0); + y->p_size = 0; + if (i) inlet_new((t_object *)x, (t_pd *)y, 0, 0); + sprintf_proxy_checkit(y, buf, 1); + i++; + } + } + } +#if SPRINTF_DEBUG + post("printf(\"%s\", ...)", fstring); +#endif + outlet_new((t_object *)x, &s_anything); + return (x); +} + +void sprintf_setup(void) +{ + sprintf_class = class_new(gensym("sprintf"), + (t_newmethod)sprintf_new, + (t_method)sprintf_free, + sizeof(t_sprintf), 0, A_GIMME, 0); + class_addbang(sprintf_class, sprintf_bang); + class_addfloat(sprintf_class, sprintf_float); + class_addsymbol(sprintf_class, sprintf_symbol); + class_addlist(sprintf_class, sprintf_list); + class_addanything(sprintf_class, sprintf_anything); + sprintf_proxy_class = class_new(gensym("_sprintf_proxy"), 0, 0, + sizeof(t_sprintf_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(sprintf_proxy_class, sprintf_proxy_bang); + class_addfloat(sprintf_proxy_class, sprintf_proxy_float); + class_addsymbol(sprintf_proxy_class, sprintf_proxy_symbol); + class_addlist(sprintf_proxy_class, sprintf_proxy_list); + class_addanything(sprintf_proxy_class, sprintf_proxy_anything); +} diff --git a/cyclone/hammer/substitute.c b/cyclone/hammer/substitute.c new file mode 100644 index 0000000..48a9b9d --- /dev/null +++ b/cyclone/hammer/substitute.c @@ -0,0 +1,340 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define SUBSTITUTE_INISIZE 32 /* LATER rethink */ +#define SUBSTITUTE_MAXSIZE 256 + +typedef struct _substitute +{ + t_object x_ob; + t_pd *x_proxy; + t_atom x_match; + t_atom x_repl; + int x_size; /* as allocated */ + t_atom *x_message; + t_atom x_messini[SUBSTITUTE_INISIZE]; + int x_entered; + t_atom x_auxmatch; + t_atom x_auxrepl; + t_outlet *x_passout; +} t_substitute; + +typedef struct _substitute_proxy +{ + t_object p_ob; + t_atom *p_match; /* pointing to parent's (aux)match */ + t_atom *p_repl; +} t_substitute_proxy; + +static t_class *substitute_class; +static t_class *substitute_proxy_class; + +/* LATER rethink */ +static void substitute_dooutput(t_substitute *x, + t_symbol *s, int ac, t_atom *av, int pass) +{ + t_outlet *out = (pass ? x->x_passout : ((t_object *)x)->ob_outlet); + if (s == &s_float) + { + if (ac > 1) + outlet_list(out, &s_list, ac, av); + else + outlet_float(out, av->a_w.w_float); + } + else if (s == &s_bang && !ac) /* CHECKED */ + outlet_bang(out); + else if (s == &s_symbol && ac == 1 && av->a_type == A_SYMBOL) + outlet_symbol(out, av->a_w.w_symbol); + else if (s) + outlet_anything(out, s, ac, av); + else if (ac) + outlet_list(out, &s_list, ac, av); +} + +static int substitute_check(t_substitute *x, t_symbol *s, int ac, t_atom *av) +{ + if (x->x_repl.a_type == A_NULL) + return (-2); + /* see substitute_proxy_validate() for possible types and values */ + if (x->x_match.a_type == A_FLOAT) + { + t_float f = x->x_match.a_w.w_float; + int i; + for (i = 0; i < ac; i++, av++) + if (av->a_type == A_FLOAT && av->a_w.w_float == f) + return (i); + } + else if (x->x_match.a_type == A_SYMBOL) + { + /* match symbol is validated -- never null */ + t_symbol *match = x->x_match.a_w.w_symbol; + int i; + if (s == match) + return (-1); + for (i = 0; i < ac; i++, av++) + if (av->a_type == A_SYMBOL && av->a_w.w_symbol == match) + return (i); + } + return (-2); +} + +static void substitute_doit(t_substitute *x, + t_symbol *s, int ac, t_atom *av, int startndx) +{ + int cnt = ac - startndx; + if (cnt > 0) + { + t_atom *ap = av + startndx; + if (x->x_match.a_type == A_FLOAT) + { + t_float f = x->x_match.a_w.w_float; + while (cnt--) + { + if (ap->a_type == A_FLOAT && ap->a_w.w_float == f) + *ap = x->x_repl; + ap++; + } + } + else if (x->x_match.a_type == A_SYMBOL) + { + t_symbol *match = x->x_match.a_w.w_symbol; + while (cnt--) + { + if (ap->a_type == A_SYMBOL && ap->a_w.w_symbol == match) + *ap = x->x_repl; + ap++; + } + } + } + substitute_dooutput(x, s, ac, av, 0); +} + +static void substitute_anything(t_substitute *x, + t_symbol *s, int ac, t_atom *av) +{ + int matchndx = substitute_check(x, s, ac, av); + if (matchndx < -1) + substitute_dooutput(x, s, ac, av, 1); + else + { + int reentered = x->x_entered; + int prealloc = !reentered; + int ntotal = ac; + t_atom *buf; + t_substitute_proxy *proxy = (t_substitute_proxy *)x->x_proxy; + x->x_entered = 1; + proxy->p_match = &x->x_auxmatch; + proxy->p_repl = &x->x_auxrepl; + if (s == &s_) s = 0; + if (matchndx == -1) + { + if (x->x_repl.a_type == A_FLOAT) + { + ntotal++; + if (ac) s = &s_list; + else s = &s_float; + } + else if (x->x_repl.a_type == A_SYMBOL) + { + s = x->x_repl.a_w.w_symbol; + matchndx = 0; + } + } + else if (matchndx == 0 + && (!s || s == &s_list || s == &s_float) + && av->a_type == A_FLOAT + && x->x_repl.a_type == A_SYMBOL) + { + s = x->x_repl.a_w.w_symbol; + ac--; + av++; + ntotal = ac; + } + if (prealloc && ac > x->x_size) + { + if (ntotal > SUBSTITUTE_MAXSIZE) + prealloc = 0; + else + x->x_message = grow_nodata(&ntotal, &x->x_size, x->x_message, + SUBSTITUTE_INISIZE, x->x_messini, + sizeof(*x->x_message)); + } + if (prealloc) buf = x->x_message; + else + /* LATER consider using the stack if ntotal <= MAXSTACK */ + buf = getbytes(ntotal * sizeof(*buf)); + if (buf) + { + int ncopy = ntotal; + t_atom *bp = buf; + if (matchndx == -1) + { + SETFLOAT(bp++, x->x_repl.a_w.w_float); + ncopy--; + } + if (ncopy) + memcpy(bp, av, ncopy * sizeof(*buf)); + substitute_doit(x, s, ntotal, buf, matchndx); + if (buf != x->x_message) + freebytes(buf, ntotal * sizeof(*buf)); + } + if (!reentered) + { + x->x_entered = 0; + if (x->x_auxmatch.a_type != A_NULL) + { + x->x_match = x->x_auxmatch; + x->x_auxmatch.a_type = A_NULL; + } + if (x->x_auxrepl.a_type != A_NULL) + { + x->x_repl = x->x_auxrepl; + x->x_auxrepl.a_type = A_NULL; + } + proxy->p_match = &x->x_match; + proxy->p_repl = &x->x_repl; + } + } +} + +static void substitute_bang(t_substitute *x) +{ + substitute_anything(x, &s_bang, 0, 0); +} + +static void substitute_float(t_substitute *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + substitute_anything(x, 0, 1, &at); +} + +/* CHECKED (but LATER rethink) */ +static void substitute_symbol(t_substitute *x, t_symbol *s) +{ + t_atom at; + SETSYMBOL(&at, s); + substitute_anything(x, &s_symbol, 1, &at); +} + +/* LATER gpointer */ + +static void substitute_list(t_substitute *x, t_symbol *s, int ac, t_atom *av) +{ + substitute_anything(x, 0, ac, av); +} + +static int substitute_atomvalidate(t_atom *ap) +{ + return (ap->a_type == A_FLOAT + || (ap->a_type == A_SYMBOL + && ap->a_w.w_symbol && ap->a_w.w_symbol != &s_)); +} + +/* CHECKED: 'set' is ignored, single '<atom>' does not modify a replacement */ +static void substitute_proxy_anything(t_substitute_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + if (s == &s_) s = 0; + if (s) + { + SETSYMBOL(x->p_match, s); + if (ac && substitute_atomvalidate(av)) + *x->p_repl = *av; + } + else if (ac && substitute_atomvalidate(av)) + { + *x->p_match = *av++; + if (ac > 1 && substitute_atomvalidate(av)) + *x->p_repl = *av; + } +} + +static void substitute_proxy_bang(t_substitute_proxy *x) +{ + SETSYMBOL(x->p_match, &s_bang); +} + +static void substitute_proxy_float(t_substitute_proxy *x, t_float f) +{ + SETFLOAT(x->p_match, f); +} + +/* CHECKED (but LATER rethink) */ +static void substitute_proxy_symbol(t_substitute_proxy *x, t_symbol *s) +{ + SETSYMBOL(x->p_match, &s_symbol); + SETSYMBOL(x->p_repl, s); +} + +/* LATER gpointer */ + +static void substitute_proxy_list(t_substitute_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + substitute_proxy_anything(x, 0, ac, av); +} + +static void substitute_free(t_substitute *x) +{ + if (x->x_proxy) pd_free(x->x_proxy); + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); +} + +static void *substitute_new(t_symbol *s, int ac, t_atom *av) +{ + t_substitute *x = 0; + t_substitute_proxy *proxy = + (t_substitute_proxy *)pd_new(substitute_proxy_class); + if (proxy) + { + x = (t_substitute *)pd_new(substitute_class); + proxy->p_match = &x->x_match; + proxy->p_repl = &x->x_repl; + x->x_proxy = (t_pd *)proxy; + x->x_size = SUBSTITUTE_INISIZE; + x->x_message = x->x_messini; + x->x_entered = 0; + /* CHECKED: everything is to be passed unchanged, until both are set */ + /* CHECKED: max crashes if a match has been set, but not a replacement, + and there is a match */ + x->x_match.a_type = x->x_repl.a_type = A_NULL; + x->x_auxmatch.a_type = x->x_auxrepl.a_type = A_NULL; + inlet_new((t_object *)x, (t_pd *)proxy, 0, 0); + outlet_new((t_object *)x, &s_anything); + /* CHECKED (refman error: 'a bang is sent') */ + x->x_passout = outlet_new((t_object *)x, &s_anything); + substitute_proxy_anything(proxy, 0, ac, av); + } + return (x); +} + +void substitute_setup(void) +{ + substitute_class = class_new(gensym("substitute"), + (t_newmethod)substitute_new, + (t_method)substitute_free, + sizeof(t_substitute), 0, + A_GIMME, 0); + class_addbang(substitute_class, substitute_bang); + class_addfloat(substitute_class, substitute_float); + class_addsymbol(substitute_class, substitute_symbol); + class_addlist(substitute_class, substitute_list); + class_addanything(substitute_class, substitute_anything); + substitute_proxy_class = class_new(gensym("_substitute_proxy"), 0, 0, + sizeof(t_substitute_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(substitute_proxy_class, substitute_proxy_bang); + class_addfloat(substitute_proxy_class, substitute_proxy_float); + class_addsymbol(substitute_proxy_class, substitute_proxy_symbol); + class_addlist(substitute_proxy_class, substitute_proxy_list); + class_addanything(substitute_proxy_class, substitute_proxy_anything); + class_addmethod(substitute_proxy_class, (t_method)substitute_proxy_list, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/hammer/sustain.c b/cyclone/hammer/sustain.c new file mode 100644 index 0000000..975e6aa --- /dev/null +++ b/cyclone/hammer/sustain.c @@ -0,0 +1,85 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" + +#define SUSTAIN_NPITCHES 128 + +typedef struct _sustain +{ + t_object x_ob; + t_float x_velocity; + int x_switch; + unsigned char x_pitches[SUSTAIN_NPITCHES]; + t_outlet *x_voutlet; +} t_sustain; + +static t_class *sustain_class; + +static void sustain_float(t_sustain *x, t_float f) +{ + int pitch = (int)f; + if (pitch >= 0 && pitch < SUSTAIN_NPITCHES) + { + if (x->x_velocity || !x->x_switch) + { + outlet_float(x->x_voutlet, x->x_velocity); + outlet_float(((t_object *)x)->ob_outlet, pitch); + } + else x->x_pitches[pitch]++; + } +} + +static void sustain_bang(t_sustain *x) +{ + int i; + unsigned char *pp; + for (i = 0, pp = x->x_pitches; i < SUSTAIN_NPITCHES; i++, pp++) + { + while (*pp) + { + outlet_float(x->x_voutlet, 0); + outlet_float(((t_object *)x)->ob_outlet, i); + (*pp)--; + } + } +} + +static void sustain_clear(t_sustain *x) +{ + memset(x->x_pitches, 0, sizeof(x->x_pitches)); +} + +static void sustain_ft2(t_sustain *x, t_floatarg f) +{ + int newstate = ((int)f != 0); + if (x->x_switch && !newstate) sustain_bang(x); + x->x_switch = newstate; +} + +static void *sustain_new(void) +{ + t_sustain *x = (t_sustain *)pd_new(sustain_class); + x->x_velocity = 0; + x->x_switch = 0; + sustain_clear(x); + floatinlet_new((t_object *)x, &x->x_velocity); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); + outlet_new((t_object *)x, &s_float); + x->x_voutlet = outlet_new((t_object *)x, &s_float); + return (x); +} + +void sustain_setup(void) +{ + sustain_class = class_new(gensym("sustain"), + (t_newmethod)sustain_new, + 0, /* CHECKED: no flushout */ + sizeof(t_sustain), 0, 0); + class_addfloat(sustain_class, sustain_float); + class_addbang(sustain_class, sustain_bang); + class_addmethod(sustain_class, (t_method)sustain_ft2, + gensym("ft2"), A_FLOAT, 0); +} diff --git a/cyclone/hammer/switch.c b/cyclone/hammer/switch.c new file mode 100644 index 0000000..69317a1 --- /dev/null +++ b/cyclone/hammer/switch.c @@ -0,0 +1,152 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/loud.h" + +#define SWITCH_MININLETS 2 /* LATER consider using 1 (with a warning) */ +#define SWITCH_MAXINLETS 100 +#define SWITCH_DEFINLETS 2 + +typedef struct _switch +{ + t_object x_ob; + int x_open; + int x_ninlets; /* not counting left one */ + int x_nproxies; /* as requested (and allocated) */ + t_pd **x_proxies; +} t_switch; + +typedef struct _switch_proxy +{ + t_object p_ob; + t_switch *p_master; + int p_id; +} t_switch_proxy; + +static t_class *switch_class; +static t_class *switch_proxy_class; + +static void switch_proxy_bang(t_switch_proxy *x) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_bang(((t_object *)master)->ob_outlet); +} + +static void switch_proxy_float(t_switch_proxy *x, t_float f) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_float(((t_object *)master)->ob_outlet, f); +} + +static void switch_proxy_symbol(t_switch_proxy *x, t_symbol *s) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_symbol(((t_object *)master)->ob_outlet, s); +} + +static void switch_proxy_pointer(t_switch_proxy *x, t_gpointer *gp) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_pointer(((t_object *)master)->ob_outlet, gp); +} + +static void switch_proxy_list(t_switch_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_list(((t_object *)master)->ob_outlet, s, ac, av); +} + +static void switch_proxy_anything(t_switch_proxy *x, + t_symbol *s, int ac, t_atom *av) +{ + t_switch *master = x->p_master; + if (master->x_open == x->p_id) + outlet_anything(((t_object *)master)->ob_outlet, s, ac, av); +} + +static void switch_float(t_switch *x, t_float f) +{ + int i = (int)f; + if (i < 0) i = -i; + if (i > x->x_ninlets) i = x->x_ninlets; + x->x_open = i; +} + +static void switch_bang(t_switch *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_open); +} + +static void switch_free(t_switch *x) +{ + if (x->x_proxies) + { + int i = x->x_ninlets; + while (i--) pd_free(x->x_proxies[i]); + freebytes(x->x_proxies, x->x_nproxies * sizeof(*x->x_proxies)); + } +} + +static void *switch_new(t_floatarg f1, t_floatarg f2) +{ + t_switch *x; + int i, ninlets, nproxies = (int)f1; + t_pd **proxies; + if (nproxies < SWITCH_MININLETS) + nproxies = SWITCH_DEFINLETS; + if (nproxies > SWITCH_MAXINLETS) + loud_incompatible_max(switch_class, SWITCH_MAXINLETS, "inlets"); + if (!(proxies = (t_pd **)getbytes(nproxies * sizeof(*proxies)))) + return (0); + for (ninlets = 0; ninlets < nproxies; ninlets++) + if (!(proxies[ninlets] = pd_new(switch_proxy_class))) break; + if (ninlets < SWITCH_MININLETS) + { + int i = ninlets; + while (i--) pd_free(proxies[i]); + freebytes(proxies, nproxies * sizeof(*proxies)); + return (0); + } + x = (t_switch *)pd_new(switch_class); + x->x_ninlets = ninlets; + x->x_nproxies = nproxies; + x->x_proxies = proxies; + for (i = 0; i < ninlets; i++) + { + t_switch_proxy *y = (t_switch_proxy *)proxies[i]; + y->p_master = x; + y->p_id = i + 1; + inlet_new((t_object *)x, (t_pd *)y, 0, 0); + } + outlet_new((t_object *)x, &s_anything); + switch_float(x, (f2 > 0 ? f2 : 0)); /* CHECKED */ + return (x); +} + +void switch_setup(void) +{ + switch_class = class_new(gensym("switch"), + (t_newmethod)switch_new, + (t_method)switch_free, + sizeof(t_switch), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(switch_class, switch_float); + class_addbang(switch_class, switch_bang); + switch_proxy_class = class_new(gensym("_switch_proxy"), 0, 0, + sizeof(t_switch_proxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addfloat(switch_proxy_class, switch_proxy_float); + class_addbang(switch_proxy_class, switch_proxy_bang); + class_addsymbol(switch_proxy_class, switch_proxy_symbol); + class_addpointer(switch_proxy_class, switch_proxy_pointer); + class_addlist(switch_proxy_class, switch_proxy_list); + class_addanything(switch_proxy_class, switch_proxy_anything); +} diff --git a/cyclone/hammer/tanh.c b/cyclone/hammer/tanh.c new file mode 100644 index 0000000..e124d4c --- /dev/null +++ b/cyclone/hammer/tanh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define tanhf tanh +#endif + +typedef struct _tanh +{ + t_object x_ob; + float x_value; +} t_tanh; + +static t_class *tanh_class; + +static void tanh_bang(t_tanh *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void tanh_float(t_tanh *x, t_float f) +{ + /* CHECKME large values */ + outlet_float(((t_object *)x)->ob_outlet, x->x_value = tanhf(f)); +} + +static void *tanh_new(t_floatarg f) +{ + t_tanh *x = (t_tanh *)pd_new(tanh_class); + /* CHECKME large values */ + x->x_value = tanhf(f); + outlet_new((t_object *)x, &s_float); + return (x); +} + +void tanh_setup(void) +{ + tanh_class = class_new(gensym("tanh"), + (t_newmethod)tanh_new, 0, + sizeof(t_tanh), 0, A_DEFFLOAT, 0); + class_addbang(tanh_class, tanh_bang); + class_addfloat(tanh_class, tanh_float); +} diff --git a/cyclone/hammer/testmess.c b/cyclone/hammer/testmess.c new file mode 100644 index 0000000..a6e8fe4 --- /dev/null +++ b/cyclone/hammer/testmess.c @@ -0,0 +1,245 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" + +#define TESTMESS_INISIZE 4 /* LATER rethink */ +#define TESTMESS_STACKSIZE 256 + +typedef struct _testmess +{ + t_object x_ob; + t_symbol *x_method; + void (*x_messfun)(struct _testmess *, t_symbol *s, int, t_atom *); + int x_appendmode; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + int x_tailwise; /* data is moved to the end of a buffer */ + t_atom *x_message; + t_atom *x_messbuf; + t_atom x_messini[TESTMESS_INISIZE]; +} t_testmess; + +static t_class *testmess_class; + +static void testmess_setnatoms(t_testmess *x, int natoms) +{ + if (x->x_tailwise) + x->x_message = x->x_messbuf + x->x_size - natoms; + else + x->x_message = x->x_messbuf; + x->x_natoms = natoms; +} + +static int testmess_makeroom(t_testmess *x, int natoms, int preserve) +{ + if (x->x_size < natoms) + { + int newsize = x->x_size * 2; + while (newsize < natoms) newsize *= 2; + post("makeroom %s %d %d %d", x->x_method->s_name, + preserve, natoms, newsize); + if (x->x_messbuf == x->x_messini) + { + if (!(x->x_messbuf = + (t_atom *)getbytes(newsize * sizeof(*x->x_messbuf)))) + { + x->x_messbuf = x->x_messini; + testmess_setnatoms(x, preserve ? x->x_natoms : 0); + return (0); + } + x->x_size = newsize; + testmess_setnatoms(x, preserve ? x->x_natoms : 0); + if (x->x_natoms) + { + if (x->x_tailwise) + memcpy(x->x_message, + x->x_messini + TESTMESS_INISIZE - x->x_natoms, + x->x_natoms * sizeof(*x->x_message)); + else + memcpy(x->x_message, + x->x_messini, x->x_natoms * sizeof(*x->x_message)); + } + } + else + { + int oldsize = x->x_size; + if (!(x->x_messbuf = + (t_atom *)resizebytes(x->x_messbuf, + x->x_size * sizeof(*x->x_messbuf), + newsize * sizeof(*x->x_messbuf)))) + { + x->x_messbuf = x->x_messini; + x->x_size = TESTMESS_INISIZE; + testmess_setnatoms(x, 0); + return (0); + } + x->x_size = newsize; + testmess_setnatoms(x, preserve ? x->x_natoms : 0); + if (x->x_natoms && x->x_tailwise) + memmove(x->x_message, x->x_messbuf + oldsize - x->x_natoms, + x->x_natoms * sizeof(*x->x_message)); + } + } + return (1); +} + +static void testmess_stackmess(t_testmess *x, t_symbol *s, int ac, t_atom *av) +{ + t_atom buf[TESTMESS_STACKSIZE]; + int natoms = x->x_natoms; + if (x->x_appendmode) + { + int left = TESTMESS_STACKSIZE - ac; + if (left < 0) ac = TESTMESS_STACKSIZE, natoms = 0; + else if (natoms > left) natoms = left; + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + if (natoms) + memcpy(buf + ac, x->x_message, natoms * sizeof(*buf)); + } + else + { + int left = TESTMESS_STACKSIZE - natoms; + if (left < 0) natoms = TESTMESS_STACKSIZE, ac = 0; + else if (ac > left) ac = left; + if (natoms) + memcpy(buf, x->x_message, natoms * sizeof(*buf)); + if (ac) + memcpy(buf + natoms, av, ac * sizeof(*buf)); + } + outlet_anything(((t_object *)x)->ob_outlet, s, natoms + ac, buf); +} + +static void testmess_heapmess(t_testmess *x, t_symbol *s, int ac, t_atom *av) +{ + int ntotal = x->x_natoms + ac; + t_atom *buf = getbytes(ntotal * sizeof(*buf)); + if (buf) + { + if (x->x_appendmode) + { + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + if (x->x_natoms) + memcpy(buf + ac, x->x_message, x->x_natoms * sizeof(*buf)); + } + else + { + if (x->x_natoms) + memcpy(buf, x->x_message, x->x_natoms * sizeof(*buf)); + if (ac) + memcpy(buf + x->x_natoms, av, ac * sizeof(*buf)); + } + outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); + freebytes(buf, ntotal * sizeof(*buf)); + } +} + +static void testmess_premess(t_testmess *x, t_symbol *s, int ac, t_atom *av) +{ + int ntotal = x->x_natoms + ac; + if (testmess_makeroom(x, ntotal, 1)) + { + t_atom *buf; + if (x->x_appendmode) + { + buf = x->x_messbuf + x->x_size - ntotal; + if (ac) + memcpy(buf, av, ac * sizeof(*buf)); + } + else + { + buf = x->x_messbuf; + if (ac) + memcpy(buf + x->x_natoms, av, ac * sizeof(*buf)); + } + outlet_anything(((t_object *)x)->ob_outlet, s, ntotal, buf); + } +} + +static void testmess_bang(t_testmess *x) +{ + if (x->x_natoms) + x->x_messfun(x, &s_list, 0, 0); +} + +static void testmess_float(t_testmess *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + x->x_messfun(x, (x->x_natoms ? &s_list : &s_float), 1, &at); +} + +static void testmess_symbol(t_testmess *x, t_symbol *s) +{ + x->x_messfun(x, s, 0, 0); +} + +static void testmess_anything(t_testmess *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_messfun(x, s, ac, av); +} + +static void testmess_set(t_testmess *x, t_floatarg f1, t_floatarg f2) +{ + int natoms = (int)f1; + if (natoms > 0 && testmess_makeroom(x, natoms * 2, 0)) + { + t_atom *ap; + int i = (int)f2;; + testmess_setnatoms(x, natoms); + ap = x->x_message; + while (natoms--) + { + SETFLOAT(ap, i); + i++; ap++; + } + } +} + +static void testmess_free(t_testmess *x) +{ + if (x->x_messbuf != x->x_messini) + freebytes(x->x_messbuf, x->x_size * sizeof(*x->x_messbuf)); +} + +static void *testmess_new(t_symbol *s, t_floatarg f) +{ + t_testmess *x = (t_testmess *)pd_new(testmess_class); + x->x_appendmode = 1; + x->x_tailwise = 0; + if (s == gensym("stack")) + x->x_method = s, x->x_messfun = testmess_stackmess; + else if (s == gensym("heap")) + x->x_method = s, x->x_messfun = testmess_heapmess; + else + { + x->x_method = gensym("prealloc"); + x->x_messfun = testmess_premess; + x->x_tailwise = x->x_appendmode; + } + x->x_size = TESTMESS_INISIZE; + x->x_messbuf = x->x_messini; + outlet_new((t_object *)x, &s_anything); + testmess_setnatoms(x, 0); + testmess_set(x, f, 0); + return (x); +} + +void testmess_setup(void) +{ + testmess_class = class_new(gensym("testmess"), + (t_newmethod)testmess_new, + (t_method)testmess_free, + sizeof(t_testmess), 0, + A_DEFFLOAT, A_DEFSYM, 0); + class_addbang(testmess_class, testmess_bang); + class_addfloat(testmess_class, testmess_float); + class_addsymbol(testmess_class, testmess_symbol); + class_addanything(testmess_class, testmess_anything); + class_addmethod(testmess_class, (t_method)testmess_set, + gensym("set"), A_FLOAT, A_DEFFLOAT, 0); +} diff --git a/cyclone/hammer/thresh.c b/cyclone/hammer/thresh.c new file mode 100644 index 0000000..6890dcc --- /dev/null +++ b/cyclone/hammer/thresh.c @@ -0,0 +1,134 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define THRESH_INISIZE 32 /* LATER rethink */ +#define THRESH_MAXSIZE 256 +#define THRESH_DEFTHRESH 10 + +typedef struct _thresh +{ + t_object x_ob; + t_float x_thresh; + int x_size; /* as allocated */ + int x_natoms; /* as used */ + t_atom *x_message; + t_atom x_messini[THRESH_INISIZE]; + t_clock *x_clock; +} t_thresh; + +static t_class *thresh_class; + +static void thresh_tick(t_thresh *x) +{ + int ac = x->x_natoms; + if (ac) + { + t_atom *av = x->x_message; + if (av->a_type == A_FLOAT) /* redundant, but we might need it LATER */ + { + if (ac > 1) + outlet_list(((t_object *)x)->ob_outlet, &s_list, ac, av); + else + outlet_float(((t_object *)x)->ob_outlet, av->a_w.w_float); + } + x->x_natoms = 0; + } +} + +static void thresh_anything(t_thresh *x, t_symbol *s, int ac, t_atom *av) +{ + int ntotal = x->x_natoms + ac; + t_atom *buf; + clock_unset(x->x_clock); + if (s == &s_) s = 0; + if (s) + ntotal++; + if (ntotal > x->x_size) + { + /* LATER if (ntotal > THRESH_MAXSIZE)... (cf prepend) */ + int nrequested = ntotal; + x->x_message = grow_withdata(&nrequested, &x->x_natoms, + &x->x_size, x->x_message, + THRESH_INISIZE, x->x_messini, + sizeof(*x->x_message)); + if (nrequested != ntotal) + { + x->x_natoms = 0; + if (ac >= x->x_size) + ac = (s ? x->x_size - 1 : x->x_size); + } + } + buf = x->x_message + x->x_natoms; + if (s) + { + SETSYMBOL(buf, s); + buf++; + x->x_natoms++; + } + if (ac) + { + memcpy(buf, av, ac * sizeof(*buf)); + x->x_natoms += ac; + } + clock_delay(x->x_clock, x->x_thresh); +} + +static void thresh_float(t_thresh *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + thresh_anything(x, 0, 1, &at); +} + +static void thresh_list(t_thresh *x, t_symbol *s, int ac, t_atom *av) +{ + thresh_anything(x, 0, ac, av); +} + +static void thresh_ft1(t_thresh *x, t_floatarg f) +{ + if (f < 0) + f = 0; /* CHECKED */ + x->x_thresh = f; + /* CHECKED: no rearming */ +} + +static void thresh_free(t_thresh *x) +{ + if (x->x_message != x->x_messini) + freebytes(x->x_message, x->x_size * sizeof(*x->x_message)); + if (x->x_clock) + clock_free(x->x_clock); +} + +static void *thresh_new(t_floatarg f) +{ + t_thresh *x = (t_thresh *)pd_new(thresh_class); + x->x_thresh = (f > 0 ? f : THRESH_DEFTHRESH); + x->x_size = THRESH_INISIZE; + x->x_natoms = 0; + x->x_message = x->x_messini; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_list); /* LATER rethink: list or float */ + x->x_clock = clock_new(x, (t_method)thresh_tick); + return (x); +} + +void thresh_setup(void) +{ + thresh_class = class_new(gensym("thresh"), + (t_newmethod)thresh_new, + (t_method)thresh_free, + sizeof(t_thresh), 0, + A_DEFFLOAT, 0); + class_addfloat(thresh_class, thresh_float); + class_addlist(thresh_class, thresh_list); + class_addmethod(thresh_class, (t_method)thresh_ft1, + gensym("ft1"), A_FLOAT, 0); + /* CHECKED: thresh: doesn't understand bang, symbol, anything */ +} diff --git a/cyclone/hammer/tosymbol.c b/cyclone/hammer/tosymbol.c new file mode 100644 index 0000000..8b45ad0 --- /dev/null +++ b/cyclone/hammer/tosymbol.c @@ -0,0 +1,184 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +#define TOSYMBOL_INISTRING 128 /* LATER rethink */ +#define TOSYMBOL_MAXSTRING 2048 /* the refman says so, later CHECKME */ +static char tosymbol_defseparator[] = " "; + +typedef struct _tosymbol +{ + t_object x_ob; + t_symbol *x_separator; + int x_bufsize; + char *x_buffer; + char x_bufini[TOSYMBOL_INISTRING]; + int x_entered; +} t_tosymbol; + +static t_class *tosymbol_class; +static char tosymbol_buffer[TOSYMBOL_MAXSTRING]; +static int tosymbol_bufferlocked = 0; +/* The idea is to prevent two different tosymbol objects from using the static + buffer at the same time. In the current scenario this buffer is never used + for output, so this lock is unnecessary... but it does no harm either... */ + +static void tosymbol_flushbuffer(t_tosymbol *x) +{ + if (*x->x_buffer) + { + x->x_entered = 1; + outlet_symbol(((t_object *)x)->ob_outlet, gensym(x->x_buffer)); + x->x_entered = 0; + } +} + +static void tosymbol_bang(t_tosymbol *x) +{ + outlet_bang(((t_object *)x)->ob_outlet); /* CHECKED */ +} + +static void tosymbol_float(t_tosymbol *x, t_float f) +{ + if (!x->x_entered) + { + sprintf(x->x_buffer, "%g", f); + tosymbol_flushbuffer(x); + } +} + +static void tosymbol_symbol(t_tosymbol *x, t_symbol *s) +{ + outlet_symbol(((t_object *)x)->ob_outlet, s); +} + +static void tosymbol_pointer(t_tosymbol *x, t_gpointer *gp) +{ + /* nop: otherwise gpointer would be converted to 'list <gp>' */ +} + +static int tosymbol_parse(t_symbol *s, int ac, t_atom *av, t_symbol *separator, + int bufsize, char *buffer) +{ + int nleft = bufsize - 1; + int len; + char *bp = buffer; + bp[0] = bp[nleft] = 0; + if (s) + strncpy(bp, s->s_name, nleft); + len = strlen(bp); + nleft -= len; + bp += len; + if (ac && nleft > 0) + { + char *sepstring = (separator ? + separator->s_name : tosymbol_defseparator); + while (ac--) + { + if (*sepstring && bp > buffer) + { + strncpy(bp, sepstring, nleft); + len = strlen(bp); + nleft -= len; + if (nleft <= 0) break; + bp += len; + } + /* LATER rethink: type-checking */ + atom_string(av, bp, nleft); + len = strlen(bp); + nleft -= len; + bp += len; + if (nleft <= 0) break; + av++; + } + } + if (nleft < 0) + { + bug("tosymbol_parse"); + return (bufsize); + } + return (bufsize - nleft); +} + +static void tosymbol_anything(t_tosymbol *x, t_symbol *s, int ac, t_atom *av) +{ + if (!x->x_entered) + { + if (tosymbol_bufferlocked) + { + bug("tosymbol_anything"); + tosymbol_parse(s, ac, av, x->x_separator, + x->x_bufsize, x->x_buffer); + } + else + { + int ntotal; + tosymbol_bufferlocked = 1; + ntotal = tosymbol_parse(s, ac, av, x->x_separator, + TOSYMBOL_MAXSTRING, tosymbol_buffer); + if (ntotal > x->x_bufsize) + { + int newtotal = ntotal; + x->x_buffer = grow_nodata(&newtotal, &x->x_bufsize, x->x_buffer, + TOSYMBOL_INISTRING, x->x_bufini, + sizeof(*x->x_buffer)); + if (newtotal < ntotal) + { + ntotal = newtotal - 1; + x->x_buffer[ntotal] = 0; + } + } + memcpy(x->x_buffer, tosymbol_buffer, ntotal); + tosymbol_bufferlocked = 0; + } + tosymbol_flushbuffer(x); + } +} + +static void tosymbol_list(t_tosymbol *x, t_symbol *s, int ac, t_atom *av) +{ + tosymbol_anything(x, 0, ac, av); +} + +static void tosymbol_separator(t_tosymbol *x, t_symbol *s) +{ + x->x_separator = (s ? s : &s_); /* default: empty string */ +} + +static void tosymbol_free(t_tosymbol *x) +{ + if (x->x_buffer != x->x_bufini) + freebytes(x->x_buffer, x->x_bufsize); +} + +static void *tosymbol_new(void) +{ + t_tosymbol *x = (t_tosymbol *)pd_new(tosymbol_class); + x->x_separator = 0; /* default: a space */ + x->x_bufsize = TOSYMBOL_INISTRING; + x->x_buffer = x->x_bufini; + x->x_entered = 0; + outlet_new((t_object *)x, &s_symbol); + return (x); +} + +void tosymbol_setup(void) +{ + tosymbol_class = class_new(gensym("tosymbol"), + (t_newmethod)tosymbol_new, + (t_method)tosymbol_free, + sizeof(t_tosymbol), 0, 0); + class_addbang(tosymbol_class, tosymbol_bang); + class_addfloat(tosymbol_class, tosymbol_float); + class_addsymbol(tosymbol_class, tosymbol_symbol); + class_addpointer(tosymbol_class, tosymbol_pointer); + class_addlist(tosymbol_class, tosymbol_list); + class_addanything(tosymbol_class, tosymbol_anything); + class_addmethod(tosymbol_class, (t_method)tosymbol_separator, + gensym("separator"), A_DEFSYM, 0); +} diff --git a/cyclone/hammer/universal.c b/cyclone/hammer/universal.c new file mode 100644 index 0000000..b1731d8 --- /dev/null +++ b/cyclone/hammer/universal.c @@ -0,0 +1,167 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "g_canvas.h" +#include "unstable/pd_imp.h" +#include "common/loud.h" + +/* LATER fragilize */ + +typedef struct _universal +{ + t_object x_ob; + t_glist *x_glist; + t_int x_descend; +} t_universal; + +static t_class *universal_class; + +static void universal_dobang(t_glist *glist, int descend, t_symbol *cname) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + pd_bang(&g->g_pd); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_dobang((t_glist *)g, descend, cname); +} + +static void universal_dofloat(t_glist *glist, int descend, t_symbol *cname, + t_float f) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + pd_float(&g->g_pd, f); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_dofloat((t_glist *)g, descend, cname, f); +} + +static void universal_dosymbol(t_glist *glist, int descend, t_symbol *cname, + t_symbol *s) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + pd_symbol(&g->g_pd, s); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_dosymbol((t_glist *)g, descend, cname, s); +} + +static void universal_dopointer(t_glist *glist, int descend, t_symbol *cname, + t_gpointer *gp) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + pd_pointer(&g->g_pd, gp); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_dopointer((t_glist *)g, descend, cname, gp); +} + +static void universal_dolist(t_glist *glist, int descend, t_symbol *cname, + int ac, t_atom *av) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + pd_list(&g->g_pd, &s_list, ac, av); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_dolist((t_glist *)g, descend, cname, ac, av); +} + +static void universal_doanything(t_glist *glist, int descend, t_symbol *cname, + t_symbol *s, int ac, t_atom *av) +{ + t_gobj *g; + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd)->c_name == cname) /* LATER rethink */ + typedmess(&g->g_pd, s, ac, av); + if (descend) + for (g = glist->gl_list; g; g = g->g_next) + if (pd_class(&g->g_pd) == canvas_class) /* LATER rethink */ + universal_doanything((t_glist *)g, descend, cname, s, ac, av); +} + +/* LATER rethink type-checking -- it is borrowed from typedmess(). + Anyway, do it once, before traversal, bypassing the generic mechanism + performed for every object. */ +static void universal_anything(t_universal *x, t_symbol *s, int ac, t_atom *av) +{ + /* CHECKED selector without arguments ignored with no complaints */ + if (x->x_glist && s && ac) + { + if (av->a_type == A_FLOAT) + { + if (ac > 1) + universal_dolist(x->x_glist, x->x_descend, s, ac, av); + else + universal_dofloat(x->x_glist, x->x_descend, s, av->a_w.w_float); + } + else if (av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == &s_bang) + universal_dobang(x->x_glist, x->x_descend, s); + else if (av->a_w.w_symbol == &s_float) + { + if (ac == 1) + universal_dofloat(x->x_glist, x->x_descend, s, 0.); + else if (av[1].a_type == A_FLOAT) + universal_dofloat(x->x_glist, x->x_descend, s, + av[1].a_w.w_float); + else + loud_error((t_pd *)x, "Bad argument for message 'float'"); + } + else if (av->a_w.w_symbol == &s_symbol) + universal_dosymbol(x->x_glist, x->x_descend, s, + (ac > 1 && av[1].a_type == A_SYMBOL ? + av[1].a_w.w_symbol : &s_)); + else if (av->a_w.w_symbol == &s_list) + universal_dolist(x->x_glist, x->x_descend, s, ac - 1, av + 1); + else + universal_doanything(x->x_glist, x->x_descend, s, + av->a_w.w_symbol, ac - 1, av + 1); + } + if (av->a_type == A_POINTER) + universal_dopointer(x->x_glist, x->x_descend, s, + av->a_w.w_gpointer); + } +} + +static void universal_send(t_universal *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_SYMBOL) + universal_anything(x, av->a_w.w_symbol, ac - 1, av + 1); + /* CHECKED: else ignored without complaints */ +} + +static void *universal_new(t_floatarg f) +{ + t_universal *x = (t_universal *)pd_new(universal_class); + x->x_glist = canvas_getcurrent(); + x->x_descend = ((int)f != 0); /* CHECKED */ + return (x); +} + +void universal_setup(void) +{ + universal_class = class_new(gensym("universal"), + (t_newmethod)universal_new, 0, + sizeof(t_universal), 0, A_DEFFLOAT, 0); + class_addanything(universal_class, universal_anything); + /* CHECKED: 'send', not 'sendmessage' */ + class_addmethod(universal_class, (t_method)universal_send, + gensym("send"), A_GIMME, 0); +} diff --git a/cyclone/hammer/urn.c b/cyclone/hammer/urn.c new file mode 100644 index 0000000..59b140e --- /dev/null +++ b/cyclone/hammer/urn.c @@ -0,0 +1,148 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER think again about avoiding memory allocation overhead in run-time. + One would need to use a creation argument greater than any future right + inlet value. But this is incompatible (max uses a `static', max-size + array), and should be put somewhere in the docs... */ + +#include "m_pd.h" +#include "common/loud.h" +#include "common/rand.h" +#include "common/grow.h" + +#define URN_INISIZE 128 /* LATER rethink */ +#define URN_MAXSIZE 4096 /* CHECKED */ +#define URN_MAXIMUMSIZE 65536 /* LATER use USHRT_MAX */ + +typedef struct _urn +{ + t_object x_ob; + int x_count; + int x_size; /* as allocated (in bytes) */ + int x_range; /* as used */ + unsigned short *x_urn; + unsigned short x_urnini[URN_INISIZE]; + unsigned int x_seed; + t_outlet *x_bangout; +} t_urn; + +static t_class *urn_class; + +static int urn_resize(t_urn *x, t_float f, int init) +{ + int maxmax = URN_MAXSIZE; + int range = (int)f; /* CHECKED silent truncation */ + if (init) + { + maxmax--; /* CHECKED: max 4095 here (a bug, sort of) */ + /* CHECKED in the constructor this is silent + (also > maxmax clipped without complaining) */ + if (range < 1) + range = 1; + } + else if (range < 1) + { + /* CHECKED (the same for > maxmax) */ + loud_error((t_pd *)x, "illegal size %d", f); + return (0); + } + if (range > URN_MAXIMUMSIZE) + { + loud_warning((t_pd *)x, + "requested size (%d) clipped -- effective size is %d", + range, URN_MAXIMUMSIZE); + range = URN_MAXIMUMSIZE; + } + if (range > maxmax) + loud_incompatible_max(urn_class, maxmax, "elements"); + x->x_range = range; + if (range > x->x_size) + x->x_urn = grow_nodata(&x->x_range, &x->x_size, x->x_urn, + URN_INISIZE, x->x_urnini, + sizeof(*x->x_urn)); + return (1); +} + +static void urn_bang(t_urn *x) +{ + if (x->x_count) + { + int ndx = rand_int(&x->x_seed, x->x_count); + unsigned short pick = x->x_urn[ndx]; + x->x_urn[ndx] = x->x_urn[--x->x_count]; + outlet_float(((t_object *)x)->ob_outlet, pick); + } + /* CHECKED: start banging when the first bang is input + into an empty urn (and not when the last value is output). + CHECKED: keep banging until cleared. */ + else outlet_bang(x->x_bangout); +} + +static void urn_clear(t_urn *x) +{ + int i; + x->x_count = x->x_range; + for (i = 0; i < x->x_count; i++) x->x_urn[i] = i; +} + +static void urn_float(t_urn *x, t_float f) +{ + /* CHECKED: float loudly rejected, int (any value) same as bang */ + int i; + if (loud_checkint((t_pd *)x, f, &i, &s_float)) + urn_bang(x); +} + +static void urn_ft1(t_urn *x, t_floatarg f) +{ + if (urn_resize(x, f, 0)) /* CHECKED cleared only if a legal resize */ + urn_clear(x); +} + +static void urn_seed(t_urn *x, t_floatarg f) +{ + int i = (int)f; /* CHECKED */ + if (i < 0) + i = 1; /* CHECKED */ + rand_seed(&x->x_seed, (unsigned int)i); +} + +static void urn_free(t_urn *x) +{ + if (x->x_urn != x->x_urnini) + freebytes(x->x_urn, x->x_size * sizeof(*x->x_urn)); +} + +static void *urn_new(t_floatarg f1, t_floatarg f2) +{ + t_urn *x = (t_urn *)pd_new(urn_class); + x->x_size = URN_INISIZE; + x->x_urn = x->x_urnini; + urn_resize(x, f1, 1); + urn_seed(x, f2); /* CHECKME */ + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + urn_clear(x); + return (x); +} + +void urn_setup(void) +{ + urn_class = class_new(gensym("urn"), + (t_newmethod)urn_new, + (t_method)urn_free, + sizeof(t_urn), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addbang(urn_class, urn_bang); + class_addfloat(urn_class, urn_float); + class_addmethod(urn_class, (t_method)urn_ft1, + gensym("ft1"), A_FLOAT, 0); + /* CHECKED list is auto-unfolded */ + class_addmethod(urn_class, (t_method)urn_seed, + gensym("seed"), A_FLOAT, 0); /* CHECKED arg obligatory */ + class_addmethod(urn_class, (t_method)urn_clear, + gensym("clear"), 0); +} diff --git a/cyclone/hammer/xbendin.c b/cyclone/hammer/xbendin.c new file mode 100644 index 0000000..54082b3 --- /dev/null +++ b/cyclone/hammer/xbendin.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _xbendin +{ + t_object x_ob; + int x_omni; + unsigned char x_ready; + unsigned char x_status; + unsigned char x_channel; + unsigned char x_lsb; + t_outlet *x_chanout; +} t_xbendin; + +static t_class *xbendin_class; + +static void xbendin_clear(t_xbendin *x) +{ + x->x_status = 0; + x->x_ready = 0; +} + +static void xbendin_float(t_xbendin *x, t_float f) +{ + int ival = (int)f; /* CHECKME */ + if (ival < 0) + { + /* CHECKME */ + return; + } + if (ival < 256) /* CHECKME */ + { + unsigned char bval = ival; + if (bval & 0x80) + { + unsigned char status = bval & 0xF0; + if (status == 0xF0) + { + /* CHECKME */ + if (bval < 0xF8) + xbendin_clear(x); + } + else if (status == 0xE0) + { + unsigned char channel = bval & 0x0F; + if (x->x_omni) + x->x_channel = channel; + x->x_status = (x->x_channel == channel); + x->x_ready = 0; + } + else xbendin_clear(x); + } + else if (x->x_ready) + { + if (x->x_omni) + outlet_float(x->x_chanout, x->x_channel + 1); + outlet_float(((t_object *)x)->ob_outlet, (bval << 7) + x->x_lsb); + x->x_ready = 0; + } + else if (x->x_status) + { + x->x_lsb = bval; + x->x_ready = 1; + } + } + else xbendin_clear(x); +} + +static void *xbendin_new(t_floatarg f) +{ + int channel = (int)f; /* CHECKME */ + t_xbendin *x = (t_xbendin *)pd_new(xbendin_class); + outlet_new((t_object *)x, &s_float); + if (x->x_omni = (channel == 0)) /* CHECKME */ + x->x_chanout = outlet_new((t_object *)x, &s_float); + else + x->x_channel = (unsigned char)--channel; /* CHECKME */ + xbendin_clear(x); + return (x); +} + +void xbendin_setup(void) +{ + xbendin_class = class_new(gensym("xbendin"), + (t_newmethod)xbendin_new, 0, + sizeof(t_xbendin), 0, + A_DEFFLOAT, 0); + class_addfloat(xbendin_class, xbendin_float); + /* CHECKME autocasting lists to floats */ +} diff --git a/cyclone/hammer/xbendin2.c b/cyclone/hammer/xbendin2.c new file mode 100644 index 0000000..1336800 --- /dev/null +++ b/cyclone/hammer/xbendin2.c @@ -0,0 +1,99 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +/* LATER find a better way to synchronize with xbendin, + while avoiding the c74's bug... */ + +typedef struct _xbendin2 +{ + t_object x_ob; + int x_omni; + unsigned char x_ready; + unsigned char x_status; + unsigned char x_channel; + unsigned char x_lsb; + t_outlet *x_lsbout; + t_outlet *x_chanout; +} t_xbendin2; + +static t_class *xbendin2_class; + +static void xbendin2_clear(t_xbendin2 *x) +{ + x->x_status = 0; + x->x_ready = 0; +} + +static void xbendin2_float(t_xbendin2 *x, t_float f) +{ + int ival = (int)f; /* CHECKME */ + if (ival < 0) + { + /* CHECKME */ + return; + } + if (ival < 256) /* CHECKME */ + { + unsigned char bval = ival; + if (bval & 0x80) + { + unsigned char status = bval & 0xF0; + if (status == 0xF0) + { + /* CHECKME */ + if (bval < 0xF8) + xbendin2_clear(x); + } + else if (status == 0xE0) + { + unsigned char channel = bval & 0x0F; + if (x->x_omni) + x->x_channel = channel; + x->x_status = (x->x_channel == channel); + x->x_ready = 0; + } + else xbendin2_clear(x); + } + else if (x->x_ready) + { + if (x->x_omni) + outlet_float(x->x_chanout, x->x_channel + 1); + outlet_float(x->x_lsbout, x->x_lsb); + outlet_float(((t_object *)x)->ob_outlet, bval); + x->x_ready = 0; + } + else if (x->x_status) + { + x->x_lsb = bval; + x->x_ready = 1; + } + } + else xbendin2_clear(x); +} + +static void *xbendin2_new(t_floatarg f) +{ + int channel = (int)f; /* CHECKME */ + t_xbendin2 *x = (t_xbendin2 *)pd_new(xbendin2_class); + outlet_new((t_object *)x, &s_float); + x->x_lsbout = outlet_new((t_object *)x, &s_float); + if (x->x_omni = (channel == 0)) /* CHECKME */ + x->x_chanout = outlet_new((t_object *)x, &s_float); + else + x->x_channel = (unsigned char)--channel; /* CHECKME */ + xbendin2_clear(x); + return (x); +} + +void xbendin2_setup(void) +{ + xbendin2_class = class_new(gensym("xbendin2"), + (t_newmethod)xbendin2_new, 0, + sizeof(t_xbendin2), 0, + A_DEFFLOAT, 0); + class_addfloat(xbendin2_class, xbendin2_float); + /* CHECKME autocasting lists to floats */ +} diff --git a/cyclone/hammer/xbendout.c b/cyclone/hammer/xbendout.c new file mode 100644 index 0000000..faa401e --- /dev/null +++ b/cyclone/hammer/xbendout.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _xbendout +{ + t_object x_ob; + t_float x_channel; + int x_value; +} t_xbendout; + +static t_class *xbendout_class; + +static void xbendout_dooutput(t_xbendout *x) +{ + int value = x->x_value; + int channel = (int)x->x_channel; /* CHECKME */ + if (value >= 0 && /* CHECKME */ + value <= 16383 && /* CHECKME */ + channel > 0) /* CHECKME */ + { + outlet_float(((t_object *)x)->ob_outlet, 224 + ((channel-1) & 0x0F)); + outlet_float(((t_object *)x)->ob_outlet, value & 0x7F); + outlet_float(((t_object *)x)->ob_outlet, value >> 7); + } +} + +static void xbendout_float(t_xbendout *x, t_float f) +{ + x->x_value = (int)f; /* CHECKME */ + xbendout_dooutput(x); +} + +static void *xbendout_new(t_floatarg f) +{ + t_xbendout *x = (t_xbendout *)pd_new(xbendout_class); + floatinlet_new((t_object *)x, &x->x_channel); + outlet_new((t_object *)x, &s_float); + x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */ + x->x_value = 8192; /* CHECKME if not -1 */ + return (x); +} + +void xbendout_setup(void) +{ + xbendout_class = class_new(gensym("xbendout"), + (t_newmethod)xbendout_new, 0, + sizeof(t_xbendout), 0, + A_DEFFLOAT, 0); + class_addbang(xbendout_class, xbendout_dooutput); + class_addfloat(xbendout_class, xbendout_float); +} diff --git a/cyclone/hammer/xbendout2.c b/cyclone/hammer/xbendout2.c new file mode 100644 index 0000000..a2f8817 --- /dev/null +++ b/cyclone/hammer/xbendout2.c @@ -0,0 +1,60 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _xbendout2 +{ + t_object x_ob; + t_float x_channel; + t_float x_lsb; + int x_msb; +} t_xbendout2; + +static t_class *xbendout2_class; + +static void xbendout2_dooutput(t_xbendout2 *x) +{ + int msb = x->x_msb; + int lsb = (int)x->x_lsb; /* CHECKME */ + int channel = (int)x->x_channel; /* CHECKME */ + if (msb >= 0 && /* CHECKME */ + msb <= 127 && /* CHECKME */ + lsb >= 0 && /* CHECKME */ + lsb <= 127 && /* CHECKME */ + channel > 0) /* CHECKME */ + { + outlet_float(((t_object *)x)->ob_outlet, 224 + ((channel-1) & 0x0F)); + outlet_float(((t_object *)x)->ob_outlet, lsb); + outlet_float(((t_object *)x)->ob_outlet, msb); + } +} + +static void xbendout2_float(t_xbendout2 *x, t_float f) +{ + x->x_msb = (int)f; /* CHECKME */ + xbendout2_dooutput(x); +} + +static void *xbendout2_new(t_floatarg f) +{ + t_xbendout2 *x = (t_xbendout2 *)pd_new(xbendout2_class); + floatinlet_new((t_object *)x, &x->x_lsb); + floatinlet_new((t_object *)x, &x->x_channel); + outlet_new((t_object *)x, &s_float); + x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */ + x->x_lsb = 0; + x->x_msb = 64; /* CHECKME if not -1 */ + return (x); +} + +void xbendout2_setup(void) +{ + xbendout2_class = class_new(gensym("xbendout2"), + (t_newmethod)xbendout2_new, 0, + sizeof(t_xbendout2), 0, + A_DEFFLOAT, 0); + class_addbang(xbendout2_class, xbendout2_dooutput); + class_addfloat(xbendout2_class, xbendout2_float); +} diff --git a/cyclone/hammer/xnotein.c b/cyclone/hammer/xnotein.c new file mode 100644 index 0000000..73b271b --- /dev/null +++ b/cyclone/hammer/xnotein.c @@ -0,0 +1,100 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _xnotein +{ + t_object x_ob; + int x_omni; + unsigned char x_ready; + unsigned char x_status; + unsigned char x_channel; + unsigned char x_pitch; + t_outlet *x_velout; + t_outlet *x_flagout; + t_outlet *x_chanout; +} t_xnotein; + +static t_class *xnotein_class; + +static void xnotein_clear(t_xnotein *x) +{ + x->x_status = 0; + x->x_ready = 0; +} + +static void xnotein_float(t_xnotein *x, t_float f) +{ + int ival = (int)f; /* CHECKME */ + if (ival < 0) + { + /* CHECKME */ + return; + } + if (ival < 256) /* CHECKME */ + { + unsigned char bval = ival; + if (bval & 0x80) + { + unsigned char status = bval & 0xF0; + if (status == 0xF0) + { + /* CHECKME */ + if (bval < 0xF8) + xnotein_clear(x); + } + else if (status == 0x80 || status == 0x90) + { + unsigned char channel = bval & 0x0F; + if (x->x_omni) + x->x_channel = channel; + x->x_status = (x->x_channel == channel ? status : 0); + x->x_ready = 0; + } + else xnotein_clear(x); + } + else if (x->x_ready) + { + int flag = (x->x_status == 0x90 && bval); + if (x->x_omni) + outlet_float(x->x_chanout, x->x_channel + 1); + outlet_float(x->x_flagout, flag); + outlet_float(x->x_velout, bval); + outlet_float(((t_object *)x)->ob_outlet, x->x_pitch); + x->x_ready = 0; + } + else if (x->x_status) + { + x->x_pitch = bval; + x->x_ready = 1; + } + } + else xnotein_clear(x); +} + +static void *xnotein_new(t_floatarg f) +{ + int channel = (int)f; /* CHECKME */ + t_xnotein *x = (t_xnotein *)pd_new(xnotein_class); + outlet_new((t_object *)x, &s_float); + x->x_velout = outlet_new((t_object *)x, &s_float); + x->x_flagout = outlet_new((t_object *)x, &s_float); + if (x->x_omni = (channel == 0)) /* CHECKME */ + x->x_chanout = outlet_new((t_object *)x, &s_float); + else + x->x_channel = (unsigned char)--channel; /* CHECKME */ + xnotein_clear(x); + return (x); +} + +void xnotein_setup(void) +{ + xnotein_class = class_new(gensym("xnotein"), + (t_newmethod)xnotein_new, 0, + sizeof(t_xnotein), 0, + A_DEFFLOAT, 0); + class_addfloat(xnotein_class, xnotein_float); + /* CHECKME autocasting lists to floats */ +} diff --git a/cyclone/hammer/xnoteout.c b/cyclone/hammer/xnoteout.c new file mode 100644 index 0000000..058c7f9 --- /dev/null +++ b/cyclone/hammer/xnoteout.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" + +typedef struct _xnoteout +{ + t_object x_ob; + t_float x_channel; + t_float x_flag; + t_float x_velocity; + int x_pitch; +} t_xnoteout; + +static t_class *xnoteout_class; + +static void xnoteout_dooutput(t_xnoteout *x) +{ + int status = ((int)x->x_flag ? 0x90 : 0x80); /* CHECKME */ + int channel = (int)x->x_channel; /* CHECKME */ + int pitch = x->x_pitch; + int velocity = (int)x->x_velocity & 0x7F; /* CHECKME */ + if (pitch >= 0 && /* CHECKME */ + pitch <= 127 && /* CHECKME */ + channel > 0) /* CHECKME */ + { + outlet_float(((t_object *)x)->ob_outlet, status + ((channel-1) & 0x0F)); + outlet_float(((t_object *)x)->ob_outlet, pitch); + outlet_float(((t_object *)x)->ob_outlet, velocity); + } +} + +static void xnoteout_float(t_xnoteout *x, t_float f) +{ + x->x_pitch = (int)f; /* CHECKME */ + xnoteout_dooutput(x); +} + +static void *xnoteout_new(t_floatarg f) +{ + t_xnoteout *x = (t_xnoteout *)pd_new(xnoteout_class); + floatinlet_new((t_object *)x, &x->x_velocity); + floatinlet_new((t_object *)x, &x->x_flag); + floatinlet_new((t_object *)x, &x->x_channel); + outlet_new((t_object *)x, &s_float); + x->x_channel = ((int)f > 0 ? f : 1); /* CHECKME */ + x->x_flag = 0; /* CHECKME */ + x->x_velocity = 0; /* CHECKME */ + x->x_pitch = -1; /* CHECKME */ + return (x); +} + +void xnoteout_setup(void) +{ + xnoteout_class = class_new(gensym("xnoteout"), + (t_newmethod)xnoteout_new, 0, + sizeof(t_xnoteout), 0, + A_DEFFLOAT, 0); + class_addbang(xnoteout_class, xnoteout_dooutput); + class_addfloat(xnoteout_class, xnoteout_float); +} diff --git a/cyclone/hammer/zl.c b/cyclone/hammer/zl.c new file mode 100644 index 0000000..566c18e --- /dev/null +++ b/cyclone/hammer/zl.c @@ -0,0 +1,982 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/grow.h" + +/* LATER test reentrancy, tune speedwise */ + +#define ZL_DEBUG + +#define ZL_INISIZE 32 /* LATER rethink */ +#define ZL_MAXSIZE 256 +#define ZL_MAXMODES 16 +#define ZL_DEFMODE 0 + +struct _zl; +typedef int (*t_zlintargfn)(struct _zl *, int); +typedef void (*t_zlanyargfn)(struct _zl *, t_symbol *, int, t_atom *); +typedef int (*t_zlnatomsfn)(struct _zl *); +typedef void (*t_zldoitfn)(struct _zl *, int, t_atom *); + +static int zl_nmodes = 0; +static t_symbol *zl_modesym[ZL_MAXMODES]; +static int zl_modeflags[ZL_MAXMODES]; +static t_zlintargfn zl_intargfn[ZL_MAXMODES]; +static t_zlanyargfn zl_anyargfn[ZL_MAXMODES]; +static t_zlnatomsfn zl_natomsfn[ZL_MAXMODES]; +static t_zldoitfn zl_doitfn[ZL_MAXMODES]; + +typedef struct _zldata +{ + int d_size; /* as allocated */ + int d_natoms; /* as used */ + t_atom *d_buf; + t_atom d_bufini[ZL_INISIZE]; +} t_zldata; + +typedef struct _zl +{ + t_object x_ob; + struct _zlproxy *x_proxy; + int x_entered; + int x_locked; /* locking inbuf1 in modes: iter, reg, slice */ + t_zldata x_inbuf1; + t_zldata x_inbuf2; + t_zldata x_outbuf; + int x_mode; + int x_modearg; + t_outlet *x_out2; +} t_zl; + +typedef struct _zlproxy +{ + t_object p_ob; + t_zl *p_master; +} t_zlproxy; + +static t_class *zl_class; +static t_class *zlproxy_class; + +static void zldata_init(t_zldata *d) +{ + d->d_size = ZL_INISIZE; + d->d_natoms = 0; + d->d_buf = d->d_bufini; +} + +static void zldata_free(t_zldata *d) +{ + if (d->d_buf != d->d_bufini) + freebytes(d->d_buf, d->d_size * sizeof(*d->d_buf)); +} + +static void zldata_setfloat(t_zldata *d, t_float f) +{ + SETFLOAT(d->d_buf, f); + d->d_natoms = 1; +} + +static void zldata_addfloat(t_zldata *d, t_float f) +{ + int natoms = d->d_natoms; + int nrequested = natoms + 1; + if (nrequested > d->d_size) + { + d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, + d->d_buf, ZL_INISIZE, d->d_bufini, + sizeof(*d->d_buf)); + if (natoms >= nrequested) + natoms = nrequested - 1; + } + SETFLOAT(d->d_buf + natoms, f); + d->d_natoms = natoms + 1; +} + +static void zldata_setsymbol(t_zldata *d, t_symbol *s) +{ + SETSYMBOL(d->d_buf, s); + d->d_natoms = 1; +} + +static void zldata_addsymbol(t_zldata *d, t_symbol *s) +{ + int natoms = d->d_natoms; + int nrequested = natoms + 1; + if (nrequested > d->d_size) + { + d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, + d->d_buf, ZL_INISIZE, d->d_bufini, + sizeof(*d->d_buf)); + if (natoms >= nrequested) + natoms = nrequested - 1; + } + SETSYMBOL(d->d_buf + natoms, s); + d->d_natoms = natoms + 1; +} + +static void zldata_setlist(t_zldata *d, int ac, t_atom *av) +{ + int nrequested = ac; + if (nrequested > d->d_size) + d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, + ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); + if (d->d_natoms = nrequested) + memcpy(d->d_buf, av, nrequested * sizeof(*d->d_buf)); +} + +static void zldata_addlist(t_zldata *d, int ac, t_atom *av) +{ + int natoms = d->d_natoms; + int nrequested = natoms + ac; + if (nrequested > d->d_size) + { + d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, + d->d_buf, ZL_INISIZE, d->d_bufini, + sizeof(*d->d_buf)); + if (natoms + ac > nrequested) + { + natoms = nrequested - ac; + if (natoms < 0) + natoms = 0, ac = nrequested; + } + } + if (d->d_natoms = natoms + ac) + memcpy(d->d_buf + natoms, av, ac * sizeof(*d->d_buf)); +} + +static void zldata_set(t_zldata *d, t_symbol *s, int ac, t_atom *av) +{ + if (s && s != &s_) + { + int nrequested = ac + 1; + if (nrequested > d->d_size) + d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, + ZL_INISIZE, d->d_bufini, sizeof(*d->d_buf)); + if (d->d_natoms = nrequested) + { + SETSYMBOL(d->d_buf, s); + if (--nrequested) + memcpy(d->d_buf + 1, av, nrequested * sizeof(*d->d_buf)); + } + } + else zldata_setlist(d, ac, av); +} + +static void zldata_add(t_zldata *d, t_symbol *s, int ac, t_atom *av) +{ + if (s && s != &s_) + { + int natoms = d->d_natoms; + int nrequested = natoms + 1 + ac; + if (nrequested > d->d_size) + { + d->d_buf = grow_withdata(&nrequested, &natoms, &d->d_size, + d->d_buf, ZL_INISIZE, d->d_bufini, + sizeof(*d->d_buf)); + if (natoms + 1 + ac > nrequested) + { + natoms = nrequested - 1 - ac; + if (natoms < 0) + natoms = 0, ac = nrequested - 1; + } + } + if (d->d_natoms = natoms + 1 + ac) + { + SETSYMBOL(d->d_buf + natoms, s); + if (ac > 0) + memcpy(d->d_buf + natoms + 1, av, ac * sizeof(*d->d_buf)); + } + } + else zldata_addlist(d, ac, av); +} + +/* LATER rethink */ +static void zl_dooutput(t_outlet *o, int ac, t_atom *av) +{ + if (ac > 1) + { + if (av->a_type == A_FLOAT) + outlet_list(o, &s_list, ac, av); + else if (av->a_type == A_SYMBOL) + outlet_anything(o, av->a_w.w_symbol, ac - 1, av + 1); + } + else if (ac) + { + if (av->a_type == A_FLOAT) + outlet_float(o, av->a_w.w_float); + else if (av->a_type == A_SYMBOL) +#if 1 + outlet_anything(o, av->a_w.w_symbol, 0, 0); /* CHECKED */ +#else + outlet_symbol(o, av->a_w.w_symbol); /* LATER rethink */ +#endif + } +} + +static void zl_output(t_zl *x, int ac, t_atom *av) +{ + zl_dooutput(((t_object *)x)->ob_outlet, ac, av); +} + +static void zl_output2(t_zl *x, int ac, t_atom *av) +{ + zl_dooutput(x->x_out2, ac, av); +} + +static int zl_equal(t_atom *ap1, t_atom *ap2) +{ + return (ap1->a_type == ap2->a_type + && + ((ap1->a_type == A_FLOAT + && ap1->a_w.w_float == ap2->a_w.w_float) + || + (ap1->a_type == A_SYMBOL + && ap1->a_w.w_symbol == ap2->a_w.w_symbol))); +} + +/* Mode handlers: + If zl_<mode>_count's return value is positve, then the main routine + uses an output buffer 'buf' (outbuf, or a separately allocated one). + If zl_<mode>_count's return value is zero, then the main routine is + passed a null 'buf' (see below); if it is negative, then the main + routine is not being called. + zl_<mode> (main routine) arguments: if 'buf' is null, 'natoms' + is always zero -- in modes other than len (no buffer used), group, + iter, reg, slice/ecils (inbuf1 used), there should be no output. + If 'buf' is not null, then 'natoms' is guaranteed to be positive. +*/ + +static int zl_nop_count(t_zl *x) +{ + return (0); +} + +static void zl_nop(t_zl *x, int natoms, t_atom *buf) +{ + loud_warning((t_pd *)x, "unknown mode"); +} + +static int zl_ecils_intarg(t_zl *x, int i) +{ + return (i > 0 ? i : 0); /* CHECKED */ +} + +static int zl_ecils_count(t_zl *x) +{ + return (x->x_entered ? -1 : 0); +} + +static void zl_ecils(t_zl *x, int natoms, t_atom *buf) +{ + int cnt1, cnt2 = x->x_modearg; + natoms = x->x_inbuf1.d_natoms; + buf = x->x_inbuf1.d_buf; + if (cnt2 > natoms) + cnt2 = natoms, cnt1 = 0; /* CHECKED */ + else + cnt1 = natoms - cnt2; + x->x_locked = 1; + if (cnt2) + zl_output2(x, cnt2, buf + cnt1); + if (cnt1) + zl_output(x, cnt1, buf); +} + +static int zl_group_intarg(t_zl *x, int i) +{ + return (i > 0 ? i : 0); /* CHECKED */ +} + +static int zl_group_count(t_zl *x) +{ + return (x->x_entered ? -1 : 0); +} + +static void zl_group(t_zl *x, int natoms, t_atom *buf) +{ + int cnt = x->x_modearg; + if (cnt > 0) + { + natoms = x->x_inbuf1.d_natoms; + buf = x->x_inbuf1.d_buf; + if (natoms >= cnt) + { + t_atom *from; + x->x_locked = 1; + for (from = buf; natoms >= cnt; natoms -= cnt, from += cnt) + zl_output(x, cnt, from); + x->x_inbuf1.d_natoms = natoms; + while (natoms--) *buf++ = *from++; + } + } + else x->x_inbuf1.d_natoms = 0; /* CHECKED */ +} + +static int zl_iter_intarg(t_zl *x, int i) +{ + return (i > 0 ? i : 0); /* CHECKED */ +} + +static int zl_iter_count(t_zl *x) +{ + return (x->x_entered ? + (x->x_modearg < x->x_inbuf1.d_natoms ? + x->x_modearg : x->x_inbuf1.d_natoms) + : 0); +} + +static void zl_iter(t_zl *x, int natoms, t_atom *buf) +{ + int nremaining = x->x_inbuf1.d_natoms; + t_atom *ptr = x->x_inbuf1.d_buf; + if (!buf) + { + if (natoms = (x->x_modearg < nremaining ? + x->x_modearg : nremaining)) + x->x_locked = 1; + else + return; + } + while (nremaining) + { + if (natoms > nremaining) + natoms = nremaining; + if (buf) + { + memcpy(buf, ptr, natoms * sizeof(*buf)); + zl_output(x, natoms, buf); + } + else zl_output(x, natoms, ptr); + nremaining -= natoms; + ptr += natoms; + } +} + +static int zl_join_count(t_zl *x) +{ + return (x->x_inbuf1.d_natoms + x->x_inbuf2.d_natoms); +} + +static void zl_join(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) + { + int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms; + if (ac1) + memcpy(buf, x->x_inbuf1.d_buf, ac1 * sizeof(*buf)); + if (ac2) + memcpy(buf + ac1, x->x_inbuf2.d_buf, ac2 * sizeof(*buf)); + zl_output(x, natoms, buf); + } +} + +static int zl_len_count(t_zl *x) +{ + return (0); +} + +static void zl_len(t_zl *x, int natoms, t_atom *buf) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_inbuf1.d_natoms); +} + +static int zl_nth_intarg(t_zl *x, int i) +{ + return (i > 0 ? i : 0); /* CHECKED */ +} + +static void zl_nth_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (!s && ac && av->a_type == A_FLOAT) + zldata_setlist(&x->x_inbuf2, ac - 1, av + 1); +} + +static int zl_nth_count(t_zl *x) +{ + int ac1 = x->x_inbuf1.d_natoms; + if (ac1) + { + if (x->x_modearg > 0) + return (ac1 - 1 + x->x_inbuf2.d_natoms); + else + return (x->x_entered ? ac1 : 0); + } + else return (-1); +} + +static void zl_nth(t_zl *x, int natoms, t_atom *buf) +{ + int ac1 = x->x_inbuf1.d_natoms, + ndx = x->x_modearg - 1; /* CHECKED one-based */ + if (ac1 && ndx < ac1) /* CHECKED */ + { + t_atom *av1 = x->x_inbuf1.d_buf; + if (ndx < 0) + { + if (buf) memcpy(buf, av1, ac1 * sizeof(*buf)); + else + { + buf = av1; + x->x_locked = 1; + } + zl_output2(x, ac1, buf); + } + else + { + t_atom at = av1[ndx]; + if (buf) + { + int ac2 = x->x_inbuf2.d_natoms, ntail = ac1 - ndx + 1; + t_atom *ptr = buf; + if (ndx) + { + memcpy(ptr, av1, ndx * sizeof(*buf)); + ptr += ndx; + } + if (ac2) + { + memcpy(ptr, x->x_inbuf2.d_buf, ac2 * sizeof(*buf)); + ptr += ac2; + } + if (ntail) + memcpy(ptr, av1 + ndx + 1, ntail * sizeof(*buf)); + zl_output2(x, natoms, buf); + } + zl_output(x, 1, &at); + } + } +} + +static void zl_reg_anyarg(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (!x->x_locked) + zldata_set(&x->x_inbuf1, s, ac, av); +} + +static int zl_reg_count(t_zl *x) +{ + return (x->x_entered ? x->x_inbuf1.d_natoms : 0); +} + +static void zl_reg(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf)); + else + { + natoms = x->x_inbuf1.d_natoms; + buf = x->x_inbuf1.d_buf; + x->x_locked = 1; + } + if (natoms) + zl_output(x, natoms, buf); +} + +static int zl_rev_count(t_zl *x) +{ + return (x->x_inbuf1.d_natoms); +} + +static void zl_rev(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) + { + t_atom *from = x->x_inbuf1.d_buf, *to = buf + natoms; + while (to-- > buf) + *to = *from++; + zl_output(x, natoms, buf); + } +} + +static int zl_rot_intarg(t_zl *x, int i) +{ + return (i); /* CHECKED anything goes (modulo) */ +} + +static int zl_rot_count(t_zl *x) +{ + return (x->x_inbuf1.d_natoms); +} + +static void zl_rot(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) + { + int cnt1 = x->x_modearg, cnt2; + if (cnt1) + { + if (cnt1 > 0) + { + cnt1 %= natoms; + cnt2 = natoms - cnt1; + } + else + { + cnt2 = -cnt1 % natoms; + cnt1 = natoms - cnt2; + } + /* CHECKED right rotation for positive args */ + memcpy(buf, x->x_inbuf1.d_buf + cnt2, cnt1 * sizeof(*buf)); + memcpy(buf + cnt1, x->x_inbuf1.d_buf, cnt2 * sizeof(*buf)); + } + else memcpy(buf, x->x_inbuf1.d_buf, natoms * sizeof(*buf)); + zl_output(x, natoms, buf); + } +} + +/* LATER rethink */ +static int zl_sect_count(t_zl *x) +{ + int result = 0; + int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1; + t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *ap1; + for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) + { + int i2; + t_atom *testp; + for (i2 = 0, testp = av1; i2 < i1; i2++, testp++) + if (zl_equal(ap1, testp)) + goto skip; + for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++) + { + if (zl_equal(ap1, testp)) + { + result++; + break; + } + } + skip:; + } + return (result); +} + +/* CHECKED in-buffer duplicates are skipped */ +static void zl_sect(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) + { + int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i1; + t_atom *ap1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf, *to = buf; + for (i1 = 0; i1 < ac1; i1++, ap1++) + { + int i2; + t_atom *testp; + for (testp = buf; testp < to; testp++) + if (zl_equal(ap1, testp)) + goto skip; + for (i2 = 0, testp = av2; i2 < ac2; i2++, testp++) + { + if (zl_equal(ap1, testp)) + { + *to++ = *ap1; + break; + } + } + skip:; + } + zl_output(x, natoms, buf); + } +} + +static int zl_slice_intarg(t_zl *x, int i) +{ + return (i > 0 ? i : 0); /* CHECKED */ +} + +static int zl_slice_count(t_zl *x) +{ + return (x->x_entered ? -1 : 0); +} + +static void zl_slice(t_zl *x, int natoms, t_atom *buf) +{ + int cnt1 = x->x_modearg, cnt2; + natoms = x->x_inbuf1.d_natoms; + buf = x->x_inbuf1.d_buf; + if (cnt1 > natoms) + cnt1 = natoms, cnt2 = 0; /* CHECKED */ + else + cnt2 = natoms - cnt1; + x->x_locked = 1; + if (cnt2) + zl_output2(x, cnt2, buf + cnt1); + if (cnt1) + zl_output(x, cnt1, buf); +} + +static int zl_sub_count(t_zl *x) +{ + return (0); +} + +static void zl_sub(t_zl *x, int natoms, t_atom *buf) +{ + int natoms2 = x->x_inbuf2.d_natoms; + if (natoms2) + { + int ndx1, natoms1 = x->x_inbuf1.d_natoms; + t_atom *av1 = x->x_inbuf1.d_buf, *av2 = x->x_inbuf2.d_buf; + for (ndx1 = 0; ndx1 < natoms1; ndx1++, av1++) + { + int ndx2; + t_atom *ap1 = av1, *ap2 = av2; + for (ndx2 = 0; ndx2 < natoms2; ndx2++, ap1++, ap2++) + if (!zl_equal(ap1, ap2)) + break; + if (ndx2 == natoms2) + /* CHECKED output position is zero-based */ + outlet_float(((t_object *)x)->ob_outlet, ndx1); + } + } +} + +/* LATER rethink */ +static int zl_union_count(t_zl *x) +{ + int result, ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2; + t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf; + result = ac1 + ac2; + for (i2 = 0; i2 < ac2; i2++, ap2++) + { + int i1; + t_atom *ap1; + for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) + { + if (zl_equal(ap1, ap2)) + { + result--; + break; + } + } + } + return (result); +} + +/* CHECKED in-buffer duplicates not skipped */ +static void zl_union(t_zl *x, int natoms, t_atom *buf) +{ + if (buf) + { + int ac1 = x->x_inbuf1.d_natoms, ac2 = x->x_inbuf2.d_natoms, i2; + t_atom *av1 = x->x_inbuf1.d_buf, *ap2 = x->x_inbuf2.d_buf; + if (ac1) + { + t_atom *to = buf + ac1; + memcpy(buf, av1, ac1 * sizeof(*buf)); + for (i2 = 0; i2 < ac2; i2++, ap2++) + { + int i1; + t_atom *ap1; + for (i1 = 0, ap1 = av1; i1 < ac1; i1++, ap1++) + if (zl_equal(ap1, ap2)) + break; + if (i1 == ac1) + *to++ = *ap2; + } + } + else memcpy(buf, ap2, ac2 * sizeof(*buf)); + zl_output(x, natoms, buf); + } +} + +static void zl_doit(t_zl *x) +{ + int reentered = x->x_entered; + int prealloc = !reentered; + int natoms = (*zl_natomsfn[x->x_mode])(x); + if (natoms < 0) + return; + x->x_entered = 1; + if (natoms) + { + t_zldata *d = &x->x_outbuf; + t_atom *buf; + if (prealloc && natoms > d->d_size) + { + if (natoms > ZL_MAXSIZE) + prealloc = 0; + else + { + int nrequested = natoms; + d->d_buf = grow_nodata(&nrequested, &d->d_size, d->d_buf, + ZL_INISIZE, d->d_bufini, + sizeof(*d->d_buf)); + if (nrequested != natoms) + prealloc = 0; + } + } + /* LATER consider using the stack if !prealloc && natoms <= MAXSTACK */ + if (buf = (prealloc ? d->d_buf : getbytes(natoms * sizeof(*buf)))) + { + (*zl_doitfn[x->x_mode])(x, natoms, buf); + if (buf != d->d_buf) + freebytes(buf, natoms * sizeof(*buf)); + } + } + else (*zl_doitfn[x->x_mode])(x, 0, 0); + if (!reentered) + x->x_entered = x->x_locked = 0; +} + +static void zl_bang(t_zl *x) +{ + /* CHECKED bang is a nop in len mode, LATER consider emulating this */ + /* CHECKED 'mode len, bang'->[zl]->[print] crashes max 4.0.7... */ + zl_doit(x); +} + +static void zl_float(t_zl *x, t_float f) +{ + if (!x->x_locked) + { + if (zl_modeflags[x->x_mode]) + zldata_addfloat(&x->x_inbuf1, f); + else + zldata_setfloat(&x->x_inbuf1, f); + } + zl_doit(x); +} + +static void zl_symbol(t_zl *x, t_symbol *s) +{ + if (!x->x_locked) + { + if (zl_modeflags[x->x_mode]) + zldata_addsymbol(&x->x_inbuf1, s); + else + zldata_setsymbol(&x->x_inbuf1, s); + } + zl_doit(x); +} + +/* LATER gpointer */ + +static void zl_list(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (!x->x_locked) + { + if (zl_modeflags[x->x_mode]) + zldata_addlist(&x->x_inbuf1, ac, av); + else + zldata_setlist(&x->x_inbuf1, ac, av); + } + zl_doit(x); +} + +static void zl_anything(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (!x->x_locked) + { + if (zl_modeflags[x->x_mode]) + zldata_add(&x->x_inbuf1, s, ac, av); + else + zldata_set(&x->x_inbuf1, s, ac, av); + } + zl_doit(x); +} + +static int zl_modeargfn(t_zl *x) +{ + return (zl_intargfn[x->x_mode] || zl_anyargfn[x->x_mode]); +} + +static void zl_setmodearg(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (zl_intargfn[x->x_mode]) + { + int i = (!s && ac && av->a_type == A_FLOAT ? + (int)av->a_w.w_float : /* CHECKED silent truncation */ + 0); /* CHECKED current x->x_modearg not kept */ + x->x_modearg = (*zl_intargfn[x->x_mode])(x, i); + } + if (zl_anyargfn[x->x_mode]) + (*zl_anyargfn[x->x_mode])(x, s, ac, av); +} + +static void zl_mode(t_zl *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_SYMBOL) + { + t_symbol *modesym = av->a_w.w_symbol; + int i; + for (i = 0; i < zl_nmodes; i++) + if (modesym == zl_modesym[i]) + break; + /* LATER consider making this compatible: + CHECKED setting unknown mode makes a zl nop */ + if (i && i < zl_nmodes) + { + x->x_mode = i; + zl_setmodearg(x, 0, ac - 1, av + 1); + } + } +} + +static void zlproxy_bang(t_zlproxy *d) +{ + /* CHECKED a nop */ +} + +static void zlproxy_float(t_zlproxy *p, t_float f) +{ + t_zl *x = p->p_master; + if (zl_modeargfn(x)) + { + t_atom at; + SETFLOAT(&at, f); + zl_setmodearg(x, 0, 1, &at); + } + else /* CHECKED inbuf2 filled only when used */ + zldata_setfloat(&x->x_inbuf2, f); +} + +static void zlproxy_symbol(t_zlproxy *p, t_symbol *s) +{ + t_zl *x = p->p_master; + if (zl_modeargfn(x)) + { + t_atom at; + SETSYMBOL(&at, s); + zl_setmodearg(x, 0, 1, &at); + } + else /* CHECKED inbuf2 filled only when used */ + zldata_setsymbol(&x->x_inbuf2, s); +} + +/* LATER gpointer */ + +static void zlproxy_list(t_zlproxy *p, t_symbol *s, int ac, t_atom *av) +{ + if (ac) + { + t_zl *x = p->p_master; + if (zl_modeargfn(x)) + zl_setmodearg(x, 0, ac, av); + else /* CHECKED inbuf2 filled only when used */ + zldata_setlist(&x->x_inbuf2, ac, av); + } +} + +static void zlproxy_anything(t_zlproxy *p, t_symbol *s, int ac, t_atom *av) +{ + t_zl *x = p->p_master; + if (zl_modeargfn(x)) + zl_setmodearg(x, s, ac, av); + else /* CHECKED inbuf2 filled only when used */ + zldata_set(&x->x_inbuf2, s, ac, av); +} + +#ifdef ZL_DEBUG +static void zl_debug(t_zl *x, t_floatarg f) +{ + startpost("mode %s", zl_modesym[x->x_mode]->s_name); + if (zl_intargfn[x->x_mode]) + post(" %d", x->x_modearg); + else + endpost(); + if ((int)f) + { + startpost("first:"); + postatom(x->x_inbuf1.d_natoms, x->x_inbuf1.d_buf); + endpost(); + startpost("second:"); + postatom(x->x_inbuf2.d_natoms, x->x_inbuf2.d_buf); + endpost(); + } +} +#endif + +static void zl_free(t_zl *x) +{ + zldata_free(&x->x_inbuf1); + zldata_free(&x->x_inbuf2); + zldata_free(&x->x_outbuf); + if (x->x_proxy) pd_free((t_pd *)x->x_proxy); +} + +static void *zl_new(t_symbol *s, int ac, t_atom *av) +{ + t_zl *x = (t_zl *)pd_new(zl_class); + t_zlproxy *y = (t_zlproxy *)pd_new(zlproxy_class); + x->x_proxy = y; + y->p_master = x; + x->x_entered = 0; + x->x_locked = 0; + zldata_init(&x->x_inbuf1); + zldata_init(&x->x_inbuf2); + zldata_init(&x->x_outbuf); + x->x_mode = ZL_DEFMODE; + zl_mode(x, s, ac, av); + inlet_new((t_object *)x, (t_pd *)y, 0, 0); + outlet_new((t_object *)x, &s_anything); + x->x_out2 = outlet_new((t_object *)x, &s_anything); + return (x); +} + +static void zl_setupmode(char *id, int flags, + t_zlintargfn ifn, t_zlanyargfn afn, + t_zlnatomsfn nfn, t_zldoitfn dfn) +{ + if (zl_nmodes < ZL_MAXMODES) + { + zl_modesym[zl_nmodes] = gensym(id); + zl_modeflags[zl_nmodes] = flags; + zl_intargfn[zl_nmodes] = ifn; + zl_anyargfn[zl_nmodes] = afn; + zl_natomsfn[zl_nmodes] = nfn; + zl_doitfn[zl_nmodes] = dfn; + zl_nmodes++; + } + else bug("zl_setupmode"); +} + +static void zl_setupallmodes(void) +{ + zl_setupmode("unknown", 0, 0, 0, zl_nop_count, zl_nop); + zl_setupmode("ecils", 0, zl_ecils_intarg, 0, zl_ecils_count, zl_ecils); + zl_setupmode("group", 1, zl_group_intarg, 0, zl_group_count, zl_group); + zl_setupmode("iter", 0, zl_iter_intarg, 0, zl_iter_count, zl_iter); + zl_setupmode("join", 0, 0, 0, zl_join_count, zl_join); + zl_setupmode("len", 0, 0, 0, zl_len_count, zl_len); + zl_setupmode("nth", 0, zl_nth_intarg, zl_nth_anyarg, zl_nth_count, zl_nth); + zl_setupmode("reg", 0, 0, zl_reg_anyarg, zl_reg_count, zl_reg); + zl_setupmode("rev", 0, 0, 0, zl_rev_count, zl_rev); + zl_setupmode("rot", /* CHECKED (refman error) */ + 0, zl_rot_intarg, 0, zl_rot_count, zl_rot); + zl_setupmode("sect", 0, 0, 0, zl_sect_count, zl_sect); + zl_setupmode("slice", 0, zl_slice_intarg, 0, zl_slice_count, zl_slice); + zl_setupmode("sub", 0, 0, 0, zl_sub_count, zl_sub); + zl_setupmode("union", 0, 0, 0, zl_union_count, zl_union); +} + +void zl_setup(void) +{ + zl_class = class_new(gensym("zl"), + (t_newmethod)zl_new, + (t_method)zl_free, + sizeof(t_zl), 0, + A_GIMME, 0); + class_addbang(zl_class, zl_bang); + class_addfloat(zl_class, zl_float); + class_addsymbol(zl_class, zl_symbol); + class_addlist(zl_class, zl_list); + class_addanything(zl_class, zl_anything); + class_addmethod(zl_class, (t_method)zl_mode, + gensym("mode"), A_GIMME, 0); +#ifdef ZL_DEBUG + class_addmethod(zl_class, (t_method)zl_debug, + gensym("debug"), A_DEFFLOAT, 0); +#endif + zlproxy_class = class_new(gensym("_zlproxy"), 0, 0, + sizeof(t_zlproxy), + CLASS_PD | CLASS_NOINLET, 0); + class_addbang(zlproxy_class, zlproxy_bang); + class_addfloat(zlproxy_class, zlproxy_float); + class_addsymbol(zlproxy_class, zlproxy_symbol); + class_addlist(zlproxy_class, zlproxy_list); + class_addanything(zlproxy_class, zlproxy_anything); + zl_setupallmodes(); +} diff --git a/cyclone/shadow/Makefile b/cyclone/shadow/Makefile new file mode 100644 index 0000000..b700e5e --- /dev/null +++ b/cyclone/shadow/Makefile @@ -0,0 +1,7 @@ +ROOT_DIR = ../.. +redefault: default $(ROOT_DIR)/bin/cyclist +include $(ROOT_DIR)/Makefile.common + +$(ROOT_DIR)/bin/cyclist: $(SHARED_DIR)/common/binport.c + $(CC) -DBINPORT_STANDALONE -o $@ $< + diff --git a/cyclone/shadow/Makefile.objects b/cyclone/shadow/Makefile.objects new file mode 100644 index 0000000..f77675c --- /dev/null +++ b/cyclone/shadow/Makefile.objects @@ -0,0 +1,9 @@ +SHARED_OBJECTS = \ +common/loud.o \ +common/grow.o \ +common/binport.o \ +common/port.o \ +hammer/file.o \ +sickle/sic.o \ +unstable/fragile.o \ +unstable/loader.o diff --git a/cyclone/shadow/Makefile.sources b/cyclone/shadow/Makefile.sources new file mode 100644 index 0000000..8ba4681 --- /dev/null +++ b/cyclone/shadow/Makefile.sources @@ -0,0 +1,6 @@ +CX_SOURCES = \ +cyclone.c + +OTHER_SOURCES = \ +nettles.c \ +dummies.c diff --git a/cyclone/shadow/cyclone.c b/cyclone/shadow/cyclone.c new file mode 100644 index 0000000..047d39d --- /dev/null +++ b/cyclone/shadow/cyclone.c @@ -0,0 +1,159 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Never use forked calls in shadow code... */ + +#include <stdio.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/port.h" +#include "hammer/file.h" +#include "unstable/fragile.h" +#include "unstable/loader.h" +#include "shadow.h" +#include "../build_counter" + +typedef struct _cyclone +{ + t_object x_ob; + t_symbol *x_dir; + t_hammerfile *x_filehandle; +} t_cyclone; + +static t_class *cyclone_class; +static int cyclone_hammerndx; +static int cyclone_sicklendx; +static int cyclone_nettlesndx; +static int cyclone_dummiesndx; +static int cyclone_lastndx; + +static void cyclone_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + import_max(fn->s_name, ""); +} + +static void cyclone_import(t_cyclone *x, t_symbol *fn, t_symbol *dir) +{ + if (fn && fn != &s_) + { + if (!dir || dir == &s_) dir = x->x_dir; + import_max(fn->s_name, (dir && dir != &s_) ? dir->s_name : ""); + } + else + hammerpanel_open(x->x_filehandle); +} + +static void cyclone_click(t_cyclone *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + cyclone_import(x, 0, 0); +} + +static void cyclone_bang(t_cyclone *x) +{ + int i; + fragile_class_printnames("hammer classes are: ", + cyclone_hammerndx, cyclone_sicklendx - 1); + fragile_class_printnames("sickle classes are: ", + cyclone_sicklendx, cyclone_nettlesndx - 1); + fragile_class_printnames("nettles are: ", + cyclone_nettlesndx, cyclone_dummiesndx - 1); + if (i = dummy_nreplacements()) + post("send 'reps' message to see the list of %d \ +replacement abstractions", i); + else + post("no replacement abstractions"); + post("send 'dummies' message to see the list of %d dummy classes", + /* cyclone_lastndx points to the "_dummy" sentinel class */ + cyclone_lastndx - cyclone_dummiesndx); +} + +static void cyclone_reps(t_cyclone *x) +{ + if (dummy_nreplacements()) + dummy_printreplacements("replacement abstractions are: "); + else + post("no replacement abstractions"); +} + +static void cyclone_dummies(t_cyclone *x) +{ + fragile_class_printnames("dummies are: ", + cyclone_dummiesndx, cyclone_lastndx); +} + +static void cyclone_free(t_cyclone *x) +{ + hammerfile_free(x->x_filehandle); +} + +static void *cyclone_new(t_symbol *s) +{ + t_cyclone *x = (t_cyclone *)pd_new(cyclone_class); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, cyclone_readhook, 0, 0); + x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas)); + return (x); +} + +void cyclone_setup(void) +{ + int hresult, sresult; + hresult = sresult = LOADER_OK; + if (canvas_getcurrent()) + { + /* Loading the library by object creation is banned, because of a danger + of having some of the classes already loaded. LATER rethink. */ + loud_error(0, "apparently an attempt to create a 'cyclone' object"); + loud_errand(0, "without having cyclone library preloaded"); + return; + } + post("this is cyclone %s, %s %s build", + CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); + cyclone_class = class_new(gensym("cyclone"), + (t_newmethod)cyclone_new, + (t_method)cyclone_free, + sizeof(t_cyclone), 0, A_DEFSYM, 0); + class_addbang(cyclone_class, cyclone_bang); + class_addmethod(cyclone_class, (t_method)cyclone_reps, + gensym("reps"), 0); + class_addmethod(cyclone_class, (t_method)cyclone_dummies, + gensym("dummies"), 0); + class_addmethod(cyclone_class, (t_method)cyclone_import, + gensym("import"), A_DEFSYM, A_DEFSYM, 0); + class_addmethod(cyclone_class, (t_method)cyclone_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(cyclone_class, 0); + + cyclone_hammerndx = fragile_class_count(); + if (zgetfn(&pd_objectmaker, gensym("hammer"))) + loud_warning(0, "hammer is already loaded"); + else + hresult = unstable_load_lib("", "hammer"); + + cyclone_sicklendx = fragile_class_count(); + if (zgetfn(&pd_objectmaker, gensym("sickle"))) + loud_warning(0, "sickle is already loaded"); + else + sresult = unstable_load_lib("", "sickle"); + + cyclone_nettlesndx = fragile_class_count(); + allnettles_setup(); + + cyclone_dummiesndx = fragile_class_count(); + alldummies_setup(); + cyclone_lastndx = fragile_class_count() - 1; + + if (hresult == LOADER_NOFILE) + loud_error(0, "hammer library is missing"); + else if (sresult == LOADER_NOFILE) + loud_error(0, "sickle library is missing"); + else if (!zgetfn(&pd_objectmaker, gensym("hammer")) || + !zgetfn(&pd_objectmaker, gensym("sickle"))) + { + loud_error(0, "version mismatch"); + loud_errand(0, + "use a more recent Pd release (or recompile the cyclone)."); + } +} diff --git a/cyclone/shadow/dummies.c b/cyclone/shadow/dummies.c new file mode 100644 index 0000000..272fd45 --- /dev/null +++ b/cyclone/shadow/dummies.c @@ -0,0 +1,664 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#ifdef UNIX +#include <unistd.h> +#endif +#ifdef NT +#include <io.h> +#endif +#include "m_pd.h" +#include "common/loud.h" +#include "shadow.h" + +static int dummy_nclasses = 0; +static t_class **dummy_classes; +static int dummy_nreps = 0; + +typedef struct _dummy_slot +{ + char *s_name; + int s_nins; + int s_nouts; + int s_warned; + t_newmethod s_method; /* a specialized constructor */ +} t_dummy_slot; + +static t_object *dummy_newobject(t_symbol *s, t_dummy_slot **slotp); +static void dummy_io(t_object *x, int nins, int nouts); + +static void *dummy_2dwave_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac && av->a_type == A_SYMBOL) + { + if (ac > 3 && av[3].a_type == A_FLOAT) + nouts = (int)av[3].a_w.w_float; + } + else loud_classarg(*(t_pd *)x); + if (nouts < 1) + nouts = 1; + dummy_io(x, sl->s_nins, nouts); + return (x); +} + +static void *dummy_adoutput_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + while (ac--) + { + if (av++->a_type == A_FLOAT) nouts++; + else + { + loud_classarg(*(t_pd *)x); + break; + } + } + if (nouts < 1) + nouts = 2; + dummy_io(x, sl->s_nins, nouts); + return (x); +} + +static void *dummy_fffb_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac && av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + if (nouts < 1) + { + loud_classarg(*(t_pd *)x); + nouts = 1; + } + dummy_io(x, sl->s_nins, nouts); + return (x); +} + +static void *dummy_gate_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac && av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + if (nouts < 1) + nouts = 1; + dummy_io(x, sl->s_nins, nouts); + return (x); +} + +static void *dummy_groove_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac && av->a_type == A_SYMBOL) + { + if (ac > 1 && av[1].a_type == A_FLOAT) + nouts = (int)av[1].a_w.w_float; + } + else loud_classarg(*(t_pd *)x); + if (nouts < 1) + nouts = 1; + dummy_io(x, sl->s_nins, nouts + 1); + return (x); +} + +/* FIXME */ +static void *dummy_if_new(t_symbol *s, int ac, t_atom *av) +{ + t_object *x = dummy_newobject(s, 0); + int nins = 0; + int nouts = 1; + t_symbol *ps_out2 = gensym("out2"); + while (ac--) + { + if (av->a_type == A_SYMBOL) + { + if (av->a_w.w_symbol == ps_out2) + nouts = 2; + else + { + char *name = av->a_w.w_symbol->s_name; + if (strlen(name) >= 3 && *name == '$') + { + char c = name[2]; + if (c > '1' && c <= '9' && c > '0' + nins) + nins = c - '0'; + } + } + } + av++; + } + dummy_io(x, nins, nouts); + return (x); +} + +static void *dummy_matrix_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nins = 0, nouts = 0; + if (ac && av->a_type == A_FLOAT) + { + nins = (int)av->a_w.w_float; + if (ac > 1 && av[1].a_type == A_FLOAT) + nouts = (int)av[1].a_w.w_float; + } + if (nins < 1 || nouts < 1) + { + loud_classarg(*(t_pd *)x); + if (nins < 1) nins = 1; + if (nouts < 1) nouts = 1; + } + dummy_io(x, nins, nouts + 1); /* CHECKME */ + return (x); +} + +static void *dummy_mtr_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nios = 0; + if (ac && av->a_type == A_FLOAT) + nios = (int)av->a_w.w_float; + if (nios < 1) + nios = 1; + dummy_io(x, nios + 1, nios + 1); + return (x); +} + +/* CHECKME */ +static void *dummy_pong_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nins = 0; + if (ac) + { + if (av->a_type == A_FLOAT) + { + ac--; av++; + if (ac) + { + if (av->a_type == A_FLOAT) nins = 3; + } + else nins = 2; + } + } + else nins = 2; + if (nins < 1) + { + loud_classarg(*(t_pd *)x); + nins = 2; + } + dummy_io(x, nins, sl->s_nouts); + return (x); +} + +static void *dummy_rewire_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac && av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + else if (ac > 1 && av[1].a_type == A_FLOAT) + nouts = (int)av[1].a_w.w_float; + if (nouts < 1) + nouts = 1; /* CHECKME */ + dummy_io(x, sl->s_nins, nouts + 4); + return (x); +} + +static void *dummy_selector_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nins = 0; + if (ac && av->a_type == A_FLOAT) + nins = (int)av->a_w.w_float; + if (nins < 1) + nins = 1; + dummy_io(x, nins + 1, sl->s_nouts); + return (x); +} + +static void *dummy_sfplay_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac) + { + if (av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + else if (ac > 1 && av[1].a_type == A_FLOAT) + nouts = (int)av[1].a_w.w_float; + } + if (nouts < 1) + nouts = 1; + dummy_io(x, sl->s_nins, nouts + 1); + return (x); +} + +static void *dummy_sfrecord_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nins = 0; + if (ac && av->a_type == A_FLOAT) + nins = (int)av->a_w.w_float; + if (nins < 1) + nins = 1; + dummy_io(x, nins, sl->s_nouts); + return (x); +} + +static void *dummy_stutter_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nios = 0; + if (ac > 4 && av[4].a_type == A_FLOAT) + nios = (int)av[4].a_w.w_float; + if (nios < 1) + nios = 1; + dummy_io(x, nios + 2, nios); + return (x); +} + +static void *dummy_sxformat_new(t_symbol *s, int ac, t_atom *av) +{ + return (dummy_if_new(s, ac, av)); /* FIXME */ +} + +static void *dummy_tapout_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int warned = 0, nios = 0; + while (ac--) + if (av++->a_type == A_FLOAT) + nios++; + else if (!warned++) + loud_classarg(*(t_pd *)x); + if (nios < 1) + nios = 1; + dummy_io(x, nios, nios); + return (x); +} + +/* CHECKME */ +static void *dummy_tiCmd_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac > 1) + { + ac--; av++; + while (ac--) + { + char c = 0; + if (av->a_type == A_SYMBOL) + { + c = *av->a_w.w_symbol->s_name; + if (c == 'i' || c == 'f' || c == 'l' + || c == 'b' || c == 's' || c == 'a') + nouts++; + else + c = 0; + } + if (c == 0) + { + loud_classarg(*(t_pd *)x); + break; + } + av++; + } + } + if (nouts < 1) + nouts = 0; + dummy_io(x, sl->s_nins, nouts + 2); + return (x); +} + +/* CHECKME */ +static void *dummy_timeline_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nouts = 0; + if (ac) + { + if (av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + else if (ac > 1 && av[1].a_type == A_FLOAT) + nouts = (int)av[1].a_w.w_float; + } + if (nouts < 1) + nouts = 0; + dummy_io(x, sl->s_nins, nouts); + return (x); +} + +static void *dummy_vexpr_new(t_symbol *s, int ac, t_atom *av) +{ + return (dummy_if_new(s, ac, av)); /* FIXME */ +} + +static void *dummy_vst_tilde_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + int nins = 0, nouts = 0; + if (ac > 1 && av[1].a_type == A_FLOAT) + { + if (av->a_type == A_FLOAT) + { + nins = (int)av->a_w.w_float; + nouts = (int)av[1].a_w.w_float; + } + } + else if (ac && av->a_type == A_FLOAT) + nouts = (int)av->a_w.w_float; + if (nins < 1) + nins = 2; /* CHECKME */ + if (nouts < 1) + nouts = 2; /* CHECKME */ + dummy_io(x, nins, nouts + 4); /* CHECKME */ + return (x); +} + +static t_dummy_slot dummy_slots[] = +{ + { "2d.wave~", 4, -1, 0, (t_newmethod)dummy_2dwave_tilde_new }, + { "absolutepath", 1, 1, 0, 0 }, + { "acosh", 1, 1, 0, 0 }, + { "adoutput~", 1, -1, 0, (t_newmethod)dummy_adoutput_tilde_new }, + { "adstatus", 2, 2, 0, 0 }, + { "asinh", 1, 1, 0, 0 }, + { "atanh", 1, 1, 0, 0 }, + { "begin~", 0, 1, 0, 0 }, + { "Biquad~", 6, 1, 0, 0 }, + /* LATER try mapping bpatcher to a gop abstraction/subpatch */ + { "buffer~", 1, 2, 0, 0 }, + { "buffir~", 3, 1, 0, 0 }, + { "cd", 1, 2, 0, 0 }, /* CHECKED (refman error?) */ + { "cd~", 1, 6, 0, 0 }, /* CHECKED (refman error?) */ + { "Change", 1, 3, 0, 0 }, + { "clocker", 2, 1, 0, 0 }, + { "closebang", 0, 1, 0, 0 }, + { "colorpicker", 1, 1, 0, 0 }, + { "curve~", 3, 2, 0, 0 }, + { "date", 1, 3, 0, 0 }, + { "defer", 1, 1, 0, 0 }, /* LATER pass anything through */ + { "degrade~", 3, 1, 0, 0 }, + { "detonate", 8, 8, 0, 0 }, + { "dial", 1, 1, 0, 0 }, + { "dialog", 2, 1, 0, 0 }, + { "downsamp~", 2, 1, 0, 0 }, + { "dropfile", 1, 2, 0, 0 }, + { "dspstate~", 1, 3, 0, 0 }, + { "dsptime~", 1, 1, 0, 0 }, + { "env", 1, 1, 0, 0 }, + { "envi", 1, 1, 0, 0 }, + { "error", 1, 1, 0, 0 }, + { "ezadc~", 1, 2, 0, 0 }, + { "ezdac~", 2, 0, 0, 0 }, + { "fffb~", 1, -1, 0, (t_newmethod)dummy_fffb_tilde_new }, + /* LATER Fft~ */ + /* LATER pfft~-specific classes: fftin~, fftinfo~, fftout~ */ + { "filedate", 1, 1, 0, 0 }, + { "filein", 3, 3, 0, 0 }, + { "filepath", 1, 1, 0, 0 }, + { "filtergraph~", 8, 6, 0, 0 }, + { "folder", 1, 1, 0, 0 }, /* CHECKME 2nd outlet */ + { "follow", 1, 2, 0, 0 }, + { "fpic", 1, 0, 0, 0 }, + { "frame", 6, 0, 0, 0 }, + { "function", 1, 4, 0, 0 }, + { "gain~", 2, 2, 0, 0 }, + { "gate~", 2, -1, 0, (t_newmethod)dummy_gate_tilde_new }, + { "gestalt", 1, 2, 0, 0 }, + { "Ggate", 2, 2, 0, 0 }, + /* LATER glove? */ + { "graphic", 1, 0, 0, 0 }, + { "groove~", 3, -1, 0, (t_newmethod)dummy_groove_tilde_new }, + { "Gswitch", 3, 1, 0, 0 }, + { "hint", 1, 1, 0, 0 }, + { "if", -1, -1, 0, (t_newmethod)dummy_if_new }, + /* LATER Ifft~ */ + { "imovie", 1, 3, 0, 0 }, + { "IncDec", 1, 1, 0, 0 }, + { "info~", 1, 8, 0, 0 }, /* CHECKME nouts */ + { "ioscbank~", 4, 1, 0, 0 }, + { "Key", 0, 3, 0, 0 }, + { "Keyup", 0, 3, 0, 0 }, + { "kslider", 2, 2, 0, 0 }, + { "lcd", 1, 4, 0, 0 }, /* CHECKME nouts */ + { "led", 1, 1, 0, 0 }, + { "Line", 3, 2, 0, 0 }, + { "lores~", 3, 1, 0, 0 }, + { "matrixctrl", 1, 1, 0, 0 }, /* CHECKME nins, nouts */ + { "matrix~", -1, -1, 0, (t_newmethod)dummy_matrix_tilde_new }, + { "maximum~", 2, 1, 0, 0 }, + { "menubar", 1, 4, 0, 0 }, /* LATER parse #Xs (additional outs) */ + { "meter~", 1, 1, 0, 0 }, /* LATER consider mapping to the vu */ + { "minimum~", 2, 1, 0, 0 }, + { "movie", 1, 3, 0, 0 }, + /* CHECKME msd */ + { "mstosamps~", 1, 2, 0, 0 }, + { "mtr", -1, -1, 0, (t_newmethod)dummy_mtr_new }, + { "multiSlider", 1, 1, 0, 0 }, + { "mute~", 1, 1, 0, 0 }, + { "normalize~", 2, 1, 0, 0 }, + { "number~", 2, 2, 0, 0 }, + { "numkey", 1, 2, 0, 0 }, + { "omscontrollers", 4, 2, 0, 0 }, /* CHECKME osx */ + { "omsinfo", 2, 1, 0, 0 }, /* LATER midiinfo? */ + { "omsnotes", 4, 2, 0, 0 }, /* CHECKME osx */ + { "omspatches", 3, 2, 0, 0 }, /* CHECKME osx */ + { "onecopy", 0, 0, 0, 0 }, /* CHECKME */ + { "onepole~", 2, 1, 0, 0 }, + { "opendialog", 1, 2, 0, 0 }, + { "oscbank~", 4, 1, 0, 0 }, + { "oval", 6, 0, 0, 0 }, + { "overdrive~", 2, 1, 0, 0 }, + { "panel", 1, 0, 0, 0 }, + { "pass~", 1, 1, 0, 0 }, + { "pcontrol", 1, 1, 0, 0 }, + /* LATER pfft~ */ + { "phaseshift~", 3, 1, 0, 0 }, + { "pics", 3, 0, 0, 0 }, /* CHECKME */ + { "pics2", 3, 0, 0, 0 }, /* CHECKME */ + { "pict", 3, 0, 0, 0 }, + { "pictctrl", 1, 1, 0, 0 }, + { "pictslider", 2, 2, 0, 0 }, /* CHECKME one-dimensional mode */ + { "pink~", 1, 1, 0, 0 }, /* CHECKME inlet */ + { "playbar", 1, 2, 0, 0 }, /* CHECKME */ + { "plugconfig", 1, 0, 0, 0 }, + { "plugin~", 2, 2, 0, 0 }, + { "plugmidiin", 0, 1, 0, 0 }, + { "plugmidiout", 1, 0, 0, 0 }, + { "plugmod", 5, 3, 0, 0 }, + { "plugmorph", 2, 3, 0, 0 }, + { "plugmultiparam", 1, 2, 0, 0 }, + { "plugout~", 2, 2, 0, 0 }, /* CHECKME nouts */ + { "plugphasor~", 0, 1, 0, 0 }, /* CHECKME nouts */ + { "plugreceive~", 1, 1, 0, 0 }, + { "plugsend~", 1, 0, 0, 0 }, + { "plugstore", 1, 1, 0, 0 }, /* CHECKME nouts */ + { "plugsync~", 0, 9, 0, 0 }, /* CHECKME nouts */ + { "poke~", 3, 0, 0, 0 }, + { "Poly", 2, 4, 0, 0 }, + { "polyin", 1, 3, 0, 0 }, /* LATER parse args for nouts */ + { "polyout", 3, 0, 0, 0 }, /* CHECKME nins */ + /* LATER poly~ */ + { "pong~", -1, 1, 0, (t_newmethod)dummy_pong_tilde_new }, + { "pp", 2, 2, 0, 0 }, /* CHECKME nins */ + { "pptempo", 2, 2, 0, 0 }, + { "pptime", 4, 4, 0, 0 }, + { "preset", 1, 3, 0, 0 }, + { "radiogroup", 1, 1, 0, 0 }, + { "rate~", 2, 1, 0, 0 }, /* CHECKME */ + /* LATER settable Receive? */ + { "rect", 6, 0, 0, 0 }, + { "relativepath", 1, 1, 0, 0 }, + { "reson~", 4, 1, 0, 0 }, + { "rewire~", 1, -1, 0, (t_newmethod)dummy_rewire_tilde_new }, + { "ring", 6, 0, 0, 0 }, + { "round~", 2, 1, 0, 0 }, + { "rslider", 2, 2, 0, 0 }, + { "rtin", 1, 1, 0, 0 }, + { "sampstoms~", 1, 2, 0, 0 }, + { "savedialog", 1, 3, 0, 0 }, + { "screensize", 1, 2, 0, 0 }, + { "selector~", -1, 1, 0, (t_newmethod)dummy_selector_tilde_new }, + { "seq~", 1, 2, 0, 0 }, + { "serial", 1, 2, 0, 0 }, + { "setclock", 2, 1, 0, 0 }, + { "sfinfo~", 1, 6, 0, 0 }, /* CHECKME nouts */ + { "sflist~", 1, 0, 0, 0 }, + { "sfplay~", 1, -1, 0, (t_newmethod)dummy_sfplay_tilde_new }, + { "sfrecord~", -1, 0, 0, (t_newmethod)dummy_sfrecord_tilde_new }, + { "sndmgrin~", 0, 2, 0, 0 }, /* CHECKME */ + { "strippath", 1, 2, 0, 0 }, + { "stutter~", -1, -1, 0, (t_newmethod)dummy_stutter_tilde_new }, + { "suspend", 0, 1, 0, 0 }, + { "svf~", 3, 4, 0, 0 }, + { "swatch", 3, 2, 0, 0 }, + { "sxformat", -1, 1, 0, (t_newmethod)dummy_sxformat_new }, + { "sysexin", 1, 1, 0, 0 }, + { "Table", 2, 2, 0, 0 }, + { "tapin~", 1, 1, 0, 0 }, + { "tapout~", -1, -1, 0, (t_newmethod)dummy_tapout_tilde_new }, + { "teeth~", 6, 1, 0, 0 }, + { "tempo", 4, 1, 0, 0 }, + { "Text", 1, 1, 0, 0 }, + { "textedit", 1, 3, 0, 0 }, + { "thisobject", 1, 3, 0, 0 }, /* CHECKME */ + { "thispatcher", 1, 2, 0, 0 }, + { "thisTimeline", 1, 1, 0, 0 }, + { "thisTrack", 1, 0, 0, 0 }, + { "thispoly~", 1, 1, 0, 0 }, + { "thresh~", 3, 1, 0, 0 }, + { "tiCmd", 0, -1, 0, (t_newmethod)dummy_tiCmd_new }, + { "timeline", 1, -1, 0, (t_newmethod)dummy_timeline_new }, + { "tiOut", 1, 0, 0, 0 }, + { "timein", 3, 4, 0, 0 }, + { "timeout", 4, 0, 0, 0 }, + /* LATER touchin's inlet (Touchin?) */ + { "trunc~", 1, 1, 0, 0 }, /* CHECKME */ + { "ubutton", 1, 4, 0, 0 }, + { "umenu", 1, 2, 0, 0 }, + { "vdp", 3, 4, 0, 0 }, + { "vexpr", -1, 1, 0, (t_newmethod)dummy_vexpr_new }, + { "vpicture", 0, 0, 0, 0 }, + { "vst~", -1, -1, 0, (t_newmethod)dummy_vst_tilde_new }, + { "waveform~", 5, 6, 0, 0 }, /* CHECKME */ + { "zerox~", 1, 2, 0, 0 }, + { "zigzag~", 2, 4, 0, 0 }, + { "_dummy", 0, 0, 0, 0 } +}; + +static void *dummy_new(t_symbol *s, int ac, t_atom *av) +{ + t_dummy_slot *sl; + t_object *x = dummy_newobject(s, &sl); + dummy_io(x, sl->s_nins, sl->s_nouts); + return (x); +} + +static void dummy_io(t_object *x, int nins, int nouts) +{ + nins = (nins > 0 ? nins - 1 : 0); + while (nins--) inlet_new(x, (t_pd *)x, 0, 0); + while (nouts--) outlet_new(x, &s_anything); +} + +static t_object *dummy_newobject(t_symbol *s, t_dummy_slot **slotp) +{ + t_object *x; + t_dummy_slot *sl; + int fnd; + for (fnd = 0; fnd < dummy_nclasses; fnd++) + /* LATER compare symbols, rather than strings */ + if (dummy_classes[fnd] /* empty slot: abstraction replacement */ + && !strcmp(class_getname(dummy_classes[fnd]), s->s_name)) + break; + x = (t_object *)pd_new(dummy_classes[fnd]); + sl = &dummy_slots[fnd]; + if (fnd == dummy_nclasses) + bug("dummy_newobject"); /* create a "_dummy" in this case */ + else if (!sl->s_warned) + { + loud_warning((t_pd *)x, "dummy substitution"); + sl->s_warned = 1; + } + if (slotp) *slotp = sl; + return (x); +} + +int dummy_nreplacements(void) +{ + return (dummy_nreps); +} + +void dummy_printreplacements(char *msg) +{ + int i, len = strlen(msg); + t_dummy_slot *sl; + startpost(msg); + for (i = 0, sl = dummy_slots; i < dummy_nclasses; i++, sl++) + { + if (!dummy_classes[i]) + { + int l = 1 + strlen(sl->s_name); + if ((len += l) > 66) + { + endpost(); + startpost(" "); + len = 3 + l; + } + poststring(sl->s_name); + } + } + endpost(); +} + +void alldummies_setup(void) +{ + t_dummy_slot *sl; + int i; + dummy_nclasses = sizeof(dummy_slots)/sizeof(*dummy_slots); + /* never freed: */ + dummy_classes = getbytes(dummy_nclasses * sizeof(*dummy_classes)); + for (i = 0, sl = dummy_slots; i < dummy_nclasses; i++, sl++) + { + int fd; + char dirbuf[MAXPDSTRING], *nameptr; + if ((fd = open_via_path("", sl->s_name, ".pd", + dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0) + { + close(fd); + dummy_nreps++; + } + else + dummy_classes[i] = + class_new(gensym(sl->s_name), + sl->s_method ? sl->s_method : (t_newmethod)dummy_new, + 0, sizeof(t_object), + (sl->s_nins ? 0 : CLASS_NOINLET), A_GIMME, 0); + } + dummy_nclasses--; /* use "_dummy" as a sentinel */ +} diff --git a/cyclone/shadow/nettles.c b/cyclone/shadow/nettles.c new file mode 100644 index 0000000..d7ccb87 --- /dev/null +++ b/cyclone/shadow/nettles.c @@ -0,0 +1,549 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" +#include "shadow.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define fmodf fmod +#endif + +/* Two remaining control binops have their inputs reversed. + LATER think about float-to-int conversion -- there is no point in making + the two below compatible, while all the others are not compatible... */ + +/* CHECKED left inlet causes output (refman's error -- a total rubbish) */ + +typedef struct _rbinop +{ + t_object x_ob; + t_float x_f1; /* left inlet value */ + t_float x_f2; +} t_rbinop; + +static t_class *rminus_class; + +static void rminus_bang(t_rbinop *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_f2 - x->x_f1); +} + +static void rminus_float(t_rbinop *x, t_float f) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_f2 - (x->x_f1 = f)); +} + +static void *rminus_new(t_floatarg f) +{ + t_rbinop *x = (t_rbinop *)pd_new(rminus_class); + floatinlet_new((t_object *)x, &x->x_f2); /* CHECKED */ + outlet_new((t_object *)x, &s_float); + x->x_f1 = 0; + x->x_f2 = f; /* CHECKED */ + return (x); +} + +static t_class *rdiv_class; + +static void rdiv_bang(t_rbinop *x) +{ + if (x->x_f1 != 0.) + outlet_float(((t_object *)x)->ob_outlet, x->x_f2 / x->x_f1); + else + /* CHECKED int mode: nonnegative/0 == 0, negative/0 == -1, + float mode: positive/0 == INT_MAX, nonpositive/0 == INT_MIN + LATER rethink -- why is it INT_MAX, not FLT_MAX? */ + outlet_float(((t_object *)x)->ob_outlet, + (x->x_f2 > 0 ? SHARED_INT_MAX : SHARED_INT_MIN)); +} + +static void rdiv_float(t_rbinop *x, t_float f) +{ + x->x_f1 = f; + rdiv_bang(x); +} + +static void *rdiv_new(t_floatarg f) +{ + t_rbinop *x = (t_rbinop *)pd_new(rdiv_class); + floatinlet_new((t_object *)x, &x->x_f2); + outlet_new((t_object *)x, &s_float); + x->x_f1 = 0; + x->x_f2 = f; /* CHECKED (refman's error) */ + return (x); +} + +/* The implementation of signal relational operators below has been tuned + somewhat, mostly in order to get rid of costly int->float conversions. + Loops are not hand-unrolled, because these have proven to be slower + in all the tests performed so far. LATER find a good soul willing to + make a serious profiling research... */ + +typedef struct _sigeq +{ + t_sic x_sic; + int x_algo; +} t_sigeq; + +static t_class *sigeq_class; + +static t_int *sigeq_perform0(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; +#ifdef NETTLES_SAFE + int32 truebits; + fi.fi_f = 1.; + truebits = fi.fi_i; +#endif + while (nblock--) + { +#ifdef NETTLES_SAFE + fi.fi_i = ~((*in1++ == *in2++) - 1) & truebits; +#else + fi.fi_i = ~((*in1++ == *in2++) - 1) & SHARED_TRUEBITS; +#endif + *out++ = fi.fi_f; + } + return (w + 5); +} + +static t_int *sigeq_perform1(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) *out++ = (*in1++ == *in2++); + return (w + 5); +} + +static t_int *sigeq_perform2(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + for (; nblock; nblock -= 8, in1 += 8, in2 += 8, out += 8) + { + float f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; + float f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; + float g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; + float g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; + out[0] = f0 == g0; out[1] = f1 == g1; + out[2] = f2 == g2; out[3] = f3 == g3; + out[4] = f4 == g4; out[5] = f5 == g5; + out[6] = f6 == g6; out[7] = f7 == g7; + } + return (w + 5); +} + +static void sigeq_dsp(t_sigeq *x, t_signal **sp) +{ + switch (x->x_algo) + { + case 1: + dsp_add(sigeq_perform1, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); + break; + case 2: + dsp_add(sigeq_perform2, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); + break; + default: + dsp_add(sigeq_perform0, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); + } +} + +static void sigeq__algo(t_sigeq *x, t_floatarg f) +{ + x->x_algo = f; +} + +static void *sigeq_new(t_symbol *s, int ac, t_atom *av) +{ + t_sigeq *x = (t_sigeq *)pd_new(sigeq_class); + if (s == gensym("_==1~")) + x->x_algo = 1; + else if (s == gensym("_==2~")) + x->x_algo = 2; + else + x->x_algo = 0; + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_signeq; +static t_class *signeq_class; + +static t_int *signeq_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; + while (nblock--) + { + fi.fi_i = ~((*in1++ != *in2++) - 1) & SHARED_TRUEBITS; + *out++ = fi.fi_f; + } + return (w + 5); +} + +static void signeq_dsp(t_signeq *x, t_signal **sp) +{ + dsp_add(signeq_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *signeq_new(t_symbol *s, int ac, t_atom *av) +{ + t_signeq *x = (t_signeq *)pd_new(signeq_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_siglt; +static t_class *siglt_class; + +static t_int *siglt_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; + while (nblock--) + { + fi.fi_i = ~((*in1++ < *in2++) - 1) & SHARED_TRUEBITS; + *out++ = fi.fi_f; + } + return (w + 5); +} + +static void siglt_dsp(t_siglt *x, t_signal **sp) +{ + dsp_add(siglt_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *siglt_new(t_symbol *s, int ac, t_atom *av) +{ + t_siglt *x = (t_siglt *)pd_new(siglt_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_siggt; +static t_class *siggt_class; + +static t_int *siggt_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; + while (nblock--) + { + fi.fi_i = ~((*in1++ > *in2++) - 1) & SHARED_TRUEBITS; + *out++ = fi.fi_f; + } + return (w + 5); +} + +static void siggt_dsp(t_siggt *x, t_signal **sp) +{ + dsp_add(siggt_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *siggt_new(t_symbol *s, int ac, t_atom *av) +{ + t_siggt *x = (t_siggt *)pd_new(siggt_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_sigleq; +static t_class *sigleq_class; + +static t_int *sigleq_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; + while (nblock--) + { + fi.fi_i = ~((*in1++ <= *in2++) - 1) & SHARED_TRUEBITS; + *out++ = fi.fi_f; + } + return (w + 5); +} + +static void sigleq_dsp(t_sigleq *x, t_signal **sp) +{ + dsp_add(sigleq_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *sigleq_new(t_symbol *s, int ac, t_atom *av) +{ + t_sigleq *x = (t_sigleq *)pd_new(sigleq_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_siggeq; +static t_class *siggeq_class; + +static t_int *siggeq_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_shared_floatint fi; + while (nblock--) + { + fi.fi_i = ~((*in1++ >= *in2++) - 1) & SHARED_TRUEBITS; + *out++ = fi.fi_f; + } + return (w + 5); +} + +static void siggeq_dsp(t_siggeq *x, t_signal **sp) +{ + dsp_add(siggeq_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *siggeq_new(t_symbol *s, int ac, t_atom *av) +{ + t_siggeq *x = (t_siggeq *)pd_new(siggeq_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_sigrminus; +static t_class *sigrminus_class; + +static t_int *sigrminus_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) *out++ = *in2++ - *in1++; + return (w + 5); +} + +static void sigrminus_dsp(t_sigrminus *x, t_signal **sp) +{ + dsp_add(sigrminus_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *sigrminus_new(t_symbol *s, int ac, t_atom *av) +{ + t_sigrminus *x = (t_sigrminus *)pd_new(sigrminus_class); + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_sigrover; +static t_class *sigrover_class; + +static t_int *sigrover_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + t_float f1 = *in1++; + /* CHECKED incompatible: c74 outputs NaNs. + The line below is consistent with Pd's /~, LATER rethink. */ + /* LATER multiply by reciprocal if in1 has no signal feeders */ + *out++ = (f1 == 0. ? 0. : *in2++ / f1); + } + return (w + 5); +} + +static void sigrover_dsp(t_sigrover *x, t_signal **sp) +{ + dsp_add(sigrover_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *sigrover_new(t_symbol *s, int ac, t_atom *av) +{ + t_sigrover *x = (t_sigrover *)pd_new(sigrover_class); + /* CHECKED default 0 (refman's error), LATER rethink */ + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef t_sic t_sigmod; +static t_class *sigmod_class; + +static t_int *sigmod_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + t_float f1 = *in1++; + t_float f2 = *in2++; + /* LATER think about using ieee-754 normalization tricks */ + *out++ = (f2 == 0. ? 0. /* CHECKED */ + : fmod(f1, f2)); + } + return (w + 5); +} + +static void sigmod_dsp(t_sigmod *x, t_signal **sp) +{ + dsp_add(sigmod_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *sigmod_new(t_symbol *s, int ac, t_atom *av) +{ + t_sigmod *x = (t_sigmod *)pd_new(sigmod_class); + /* CHECKED default 0 (refman's error), LATER rethink */ + sic_inlet((t_sic *)x, 1, 0, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +typedef struct _sigaccum +{ + t_sic x_sic; + t_float x_sum; +} t_sigaccum; + +static t_class *sigaccum_class; + +static t_int *sigaccum_perform(t_int *w) +{ + t_sigaccum *x = (t_sigaccum *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float sum = x->x_sum; + while (nblock--) *out++ = (sum += *in++); + x->x_sum = sum; + return (w + 5); +} + +static void sigaccum_dsp(t_sigaccum *x, t_signal **sp) +{ + dsp_add(sigaccum_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void sigaccum_bang(t_sigaccum *x) +{ + x->x_sum = 0; +} + +static void sigaccum_set(t_sigaccum *x, t_floatarg f) +{ + x->x_sum = f; +} + +static void *sigaccum_new(t_floatarg f) +{ + t_sigaccum *x = (t_sigaccum *)pd_new(sigaccum_class); + x->x_sum = f; + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void allnettles_setup(void) +{ + rminus_class = class_new(gensym("!-"), + (t_newmethod)rminus_new, 0, + sizeof(t_rbinop), 0, A_DEFFLOAT, 0); + class_addbang(rminus_class, rminus_bang); + class_addfloat(rminus_class, rminus_float); + rdiv_class = class_new(gensym("!/"), + (t_newmethod)rdiv_new, 0, + sizeof(t_rbinop), 0, A_DEFFLOAT, 0); + class_addbang(rdiv_class, rdiv_bang); + class_addfloat(rdiv_class, rdiv_float); + + sigeq_class = class_new(gensym("==~"), + (t_newmethod)sigeq_new, 0, + sizeof(t_sigeq), 0, A_GIMME, 0); + class_addcreator((t_newmethod)sigeq_new, + gensym("_==1~"), A_GIMME, 0); + class_addcreator((t_newmethod)sigeq_new, + gensym("_==2~"), A_GIMME, 0); + sic_setup(sigeq_class, sigeq_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(sigeq_class, (t_method)sigeq__algo, + gensym("_algo"), A_FLOAT, 0); + + signeq_class = class_new(gensym("!=~"), + (t_newmethod)signeq_new, 0, + sizeof(t_signeq), 0, A_GIMME, 0); + sic_setup(signeq_class, signeq_dsp, SIC_FLOATTOSIGNAL); + siglt_class = class_new(gensym("<~"), + (t_newmethod)siglt_new, 0, + sizeof(t_siglt), 0, A_GIMME, 0); + sic_setup(siglt_class, siglt_dsp, SIC_FLOATTOSIGNAL); + siggt_class = class_new(gensym(">~"), + (t_newmethod)siggt_new, 0, + sizeof(t_siggt), 0, A_GIMME, 0); + sic_setup(siggt_class, siggt_dsp, SIC_FLOATTOSIGNAL); + sigleq_class = class_new(gensym("<=~"), + (t_newmethod)sigleq_new, 0, + sizeof(t_sigleq), 0, A_GIMME, 0); + sic_setup(sigleq_class, sigleq_dsp, SIC_FLOATTOSIGNAL); + siggeq_class = class_new(gensym(">=~"), + (t_newmethod)siggeq_new, 0, + sizeof(t_siggeq), 0, A_GIMME, 0); + sic_setup(siggeq_class, siggeq_dsp, SIC_FLOATTOSIGNAL); + sigrminus_class = class_new(gensym("!-~"), + (t_newmethod)sigrminus_new, 0, + sizeof(t_sigrminus), 0, A_GIMME, 0); + sic_setup(sigrminus_class, sigrminus_dsp, SIC_FLOATTOSIGNAL); + sigrover_class = class_new(gensym("!/~"), + (t_newmethod)sigrover_new, 0, + sizeof(t_sigrover), 0, A_GIMME, 0); + sic_setup(sigrover_class, sigrover_dsp, SIC_FLOATTOSIGNAL); + sigmod_class = class_new(gensym("%~"), + (t_newmethod)sigmod_new, 0, + sizeof(t_sigmod), 0, A_GIMME, 0); + sic_setup(sigmod_class, sigmod_dsp, SIC_FLOATTOSIGNAL); + sigaccum_class = class_new(gensym("+=~"), + (t_newmethod)sigaccum_new, 0, + sizeof(t_sigaccum), 0, A_DEFFLOAT, 0); + sic_setup(sigaccum_class, sigaccum_dsp, SIC_FLOATTOSIGNAL); + class_addbang(sigaccum_class, sigaccum_bang); + class_addmethod(sigaccum_class, (t_method)sigaccum_set, + gensym("set"), A_FLOAT, 0); +} diff --git a/cyclone/shadow/shadow.h b/cyclone/shadow/shadow.h new file mode 100644 index 0000000..aefc46e --- /dev/null +++ b/cyclone/shadow/shadow.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __SHADOW_H__ +#define __SHADOW_H__ + +void allnettles_setup(void); +void alldummies_setup(void); +int dummy_nreplacements(void); +void dummy_printreplacements(char *msg); + +#endif diff --git a/cyclone/sickle/Clip.c b/cyclone/sickle/Clip.c new file mode 100644 index 0000000..2888be1 --- /dev/null +++ b/cyclone/sickle/Clip.c @@ -0,0 +1,59 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* Clip~ substitution is needed to handle signal input for lo and hi */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define CLIP_DEFLO 0. +#define CLIP_DEFHI 0. + +typedef t_sic t_clip; +static t_class *clip_class; + +static t_int *clip_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *in3 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + while (nblock--) + { + float f = *in1++; + float lo = *in2++; + float hi = *in3++; + if (f < lo) + *out++ = lo; + else if (f > hi) + *out++ = hi; + else + *out++ = f; + } + return (w + 6); +} + +static void clip_dsp(t_clip *x, t_signal **sp) +{ + dsp_add(clip_perform, 5, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void *clip_new(t_symbol *s, int ac, t_atom *av) +{ + t_clip *x = (t_clip *)pd_new(clip_class); + sic_inlet((t_sic *)x, 1, CLIP_DEFLO, 0, ac, av); + sic_inlet((t_sic *)x, 2, CLIP_DEFHI, 1, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void Clip_tilde_setup(void) +{ + clip_class = class_new(gensym("Clip~"), + (t_newmethod)clip_new, 0, + sizeof(t_clip), 0, A_GIMME, 0); + sic_setup(clip_class, clip_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/Line.c b/cyclone/sickle/Line.c new file mode 100644 index 0000000..f1d2b18 --- /dev/null +++ b/cyclone/sickle/Line.c @@ -0,0 +1,299 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/grow.h" +#include "common/loud.h" +#include "sickle/sic.h" + +//#define LINE_DEBUG + +#ifndef PD_BADFLOAT +#define PD_BADFLOAT(f) ((((*(unsigned int*)&(f))&0x7f800000)==0) || \ + (((*(unsigned int*)&(f))&0x7f800000)==0x7f800000)) +#endif + +#define LINE_INISIZE 64 /* LATER rethink */ +#define LINE_MAXSIZE 64 + +typedef struct _lineseg +{ + float s_target; + float s_delta; +} t_lineseg; + +typedef struct _line +{ + t_sic x_sic; + float x_value; + float x_target; + float x_delta; + int x_deltaset; + float x_inc; + float x_biginc; + float x_ksr; + int x_nleft; + int x_retarget; + int x_size; /* as allocated */ + int x_nsegs; /* as used */ + t_lineseg *x_curseg; + t_lineseg *x_segs; + t_lineseg x_segini[LINE_INISIZE]; + t_clock *x_clock; + t_outlet *x_bangout; +#ifdef LINE_DEBUG + int dbg_nretargets; + int dbg_exitpoint; + int dbg_npoints; +#endif +} t_line; + +static t_class *line_class; + +static void line_tick(t_line *x) +{ + outlet_bang(x->x_bangout); +#ifdef LINE_DEBUG + post("exit point %d, after %d retarget calls", + x->dbg_exitpoint, x->dbg_nretargets); + post("at value %g, after last %d npoints, with inc %g, biginc %g", + x->x_value, x->dbg_npoints, x->x_inc, x->x_biginc); + x->dbg_nretargets = x->dbg_exitpoint = x->dbg_npoints = 0; +#endif +} + +static t_int *line_perform(t_int *w) +{ + t_line *x = (t_line *)(w[1]); + t_float *out = (t_float *)(w[2]); + int nblock = (int)(w[3]); + int nxfer = x->x_nleft; + float curval = x->x_value; + float inc = x->x_inc; + float biginc = x->x_biginc; + if (PD_BADFLOAT(curval)) /* LATER rethink */ + curval = x->x_value = 0; +retarget: + if (x->x_retarget) + { + float target = x->x_curseg->s_target; + float delta = x->x_curseg->s_delta; + int npoints = delta * x->x_ksr + 0.5; /* LATER rethink */ +#ifdef LINE_DEBUG + x->dbg_nretargets++; +#endif + x->x_nsegs--; + x->x_curseg++; + while (npoints <= 0) + { + curval = x->x_value = target; + if (x->x_nsegs) + { + target = x->x_curseg->s_target; + delta = x->x_curseg->s_delta; + npoints = delta * x->x_ksr + 0.5; /* LATER rethink */ + x->x_nsegs--; + x->x_curseg++; + } + else + { + while (nblock--) *out++ = curval; + x->x_nleft = 0; +#ifdef LINE_DEBUG + x->dbg_exitpoint = 1; +#endif + clock_delay(x->x_clock, 0); + x->x_retarget = 0; + return (w + 4); + } + } + nxfer = x->x_nleft = npoints; + inc = x->x_inc = (target - x->x_value) / (float)npoints; + x->x_biginc = (int)(w[3]) * inc; + biginc = nblock * inc; + x->x_target = target; + x->x_retarget = 0; +#ifdef LINE_DEBUG + x->dbg_npoints = npoints; +#endif + } + if (nxfer >= nblock) + { + if ((x->x_nleft -= nblock) == 0) + { + if (x->x_nsegs) x->x_retarget = 1; + else + { +#ifdef LINE_DEBUG + x->dbg_exitpoint = 2; +#endif + clock_delay(x->x_clock, 0); + } + x->x_value = x->x_target; + } + else x->x_value += biginc; + while (nblock--) + *out++ = curval, curval += inc; + } + else if (nxfer > 0) + { + nblock -= nxfer; + do + *out++ = curval, curval += inc; + while (--nxfer); + curval = x->x_value = x->x_target; + if (x->x_nsegs) + { + x->x_retarget = 1; + goto retarget; + } + else + { + while (nblock--) *out++ = curval; + x->x_nleft = 0; +#ifdef LINE_DEBUG + x->dbg_exitpoint = 3; +#endif + clock_delay(x->x_clock, 0); + } + } + else while (nblock--) *out++ = curval; + return (w + 4); +} + +static void line_float(t_line *x, t_float f) +{ + if (x->x_deltaset) + { + x->x_deltaset = 0; + x->x_target = f; + x->x_nsegs = 1; + x->x_curseg = x->x_segs; + x->x_curseg->s_target = f; + x->x_curseg->s_delta = x->x_delta; + x->x_retarget = 1; + } + else + { + x->x_value = x->x_target = f; + x->x_nsegs = 0; + x->x_curseg = 0; + x->x_nleft = 0; + x->x_retarget = 0; + } +} + +static void line_ft1(t_line *x, t_floatarg f) +{ + x->x_delta = f; + x->x_deltaset = (f > 0); +} + +static void line_list(t_line *x, t_symbol *s, int ac, t_atom *av) +{ + int natoms, nsegs, odd; + t_atom *ap; + t_lineseg *segp; + for (natoms = 0, ap = av; natoms < ac; natoms++, ap++) + if (ap->a_type != A_FLOAT) break; /* CHECKME */ + if (!natoms) + return; /* CHECKME */ + odd = natoms % 2; + nsegs = natoms / 2; + if (odd) nsegs++; + if (nsegs > x->x_size) + { + int ns = nsegs; + x->x_segs = grow_nodata(&ns, &x->x_size, x->x_segs, + LINE_INISIZE, x->x_segini, + sizeof(*x->x_segs)); + if (ns < nsegs) + { + natoms = ns * 2; + nsegs = ns; + } + } + x->x_nsegs = nsegs; +#ifdef LINE_DEBUG + post("%d segments:", x->x_nsegs); +#endif + segp = x->x_segs; + if (odd) nsegs--; + while (nsegs--) + { + segp->s_target = av++->a_w.w_float; + segp->s_delta = av++->a_w.w_float; +#ifdef LINE_DEBUG + post("%g %g", segp->s_target, segp->s_delta); +#endif + segp++; + } + if (odd) + { + segp->s_target = av->a_w.w_float; + segp->s_delta = 0; +#ifdef LINE_DEBUG + post("%g %g", segp->s_target, segp->s_delta); +#endif + } + x->x_deltaset = 0; + x->x_target = x->x_segs->s_target; + x->x_curseg = x->x_segs; + x->x_retarget = 1; +} + +/* CHECKED no stop, pity... */ +#if 0 +static void line_stop(t_line *x) +{ + x->x_target = x->x_value; + x->x_nleft = 0; + x->x_retarget = 0; + x->x_nsegs = 0; + x->x_curseg = 0; +} +#endif + +static void line_dsp(t_line *x, t_signal **sp) +{ + dsp_add(line_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + x->x_ksr = sp[0]->s_sr * 0.001; +} + +static void line_free(t_line *x) +{ + if (x->x_segs != x->x_segini) + freebytes(x->x_segs, x->x_size * sizeof(*x->x_segs)); + if (x->x_clock) clock_free(x->x_clock); +} + +static void *line_new(t_floatarg f) +{ + t_line *x = (t_line *)pd_new(line_class); + x->x_value = x->x_target = f; + x->x_deltaset = 0; + x->x_nleft = 0; + x->x_retarget = 0; + x->x_size = LINE_INISIZE; + x->x_nsegs = 0; + x->x_segs = x->x_segini; + x->x_curseg = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + x->x_clock = clock_new(x, (t_method)line_tick); + return (x); +} + +void Line_tilde_setup(void) +{ + line_class = class_new(gensym("Line~"), + (t_newmethod)line_new, 0, + sizeof(t_line), 0, A_DEFFLOAT, 0); + sic_setup(line_class, line_dsp, SIC_NOMAINSIGNALIN); + class_addfloat(line_class, line_float); + class_addlist(line_class, line_list); + class_addmethod(line_class, (t_method)line_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/Makefile b/cyclone/sickle/Makefile new file mode 100644 index 0000000..61aa444 --- /dev/null +++ b/cyclone/sickle/Makefile @@ -0,0 +1,3 @@ +ROOT_DIR = ../.. +redefault: allsickles.c default +include $(ROOT_DIR)/Makefile.common diff --git a/cyclone/sickle/Makefile.objects b/cyclone/sickle/Makefile.objects new file mode 100644 index 0000000..2edb12c --- /dev/null +++ b/cyclone/sickle/Makefile.objects @@ -0,0 +1,11 @@ +SHARED_OBJECTS = \ +unstable/forky.o \ +unstable/fragile.o \ +common/loud.o \ +common/grow.o \ +common/vefl.o \ +common/binport.o \ +common/port.o \ +hammer/file.o \ +sickle/sic.o \ +sickle/arsic.o diff --git a/cyclone/sickle/Makefile.sources b/cyclone/sickle/Makefile.sources new file mode 100644 index 0000000..e807a06 --- /dev/null +++ b/cyclone/sickle/Makefile.sources @@ -0,0 +1,67 @@ +CX_SOURCES = \ +sickle.c + +OTHER_SOURCES = \ +allsickles.c \ +abs.c \ +acos.c \ +acosh.c \ +allpass.c \ +asin.c \ +asinh.c \ +atan.c \ +atan2.c \ +atanh.c \ +average.c \ +avg.c \ +bitand.c \ +bitnot.c \ +bitor.c \ +bitshift.c \ +bitxor.c \ +capture.c \ +cartopol.c \ +change.c \ +click.c \ +Clip.c \ +comb.c \ +cosh.c \ +cosx.c \ +count.c \ +cycle.c \ +delay.c \ +delta.c \ +deltaclip.c \ +edge.c \ +frameaccum.c \ +framedelta.c \ +index.c \ +kink.c \ +Line.c \ +linedrive.c \ +log.c \ +lookup.c \ +minmax.c \ +peakamp.c \ +peek.c \ +phasewrap.c \ +play.c \ +poltocar.c \ +pow.c \ +rand.c \ +rampsmooth.c \ +record.c \ +sah.c \ +Scope.c \ +sinh.c \ +sinx.c \ +slide.c \ +Snapshot.c \ +spike.c \ +tanh.c \ +tanx.c \ +train.c \ +trapezoid.c \ +triangle.c \ +vectral.c \ +wave.c diff --git a/cyclone/sickle/Scope.c b/cyclone/sickle/Scope.c new file mode 100644 index 0000000..75e825d --- /dev/null +++ b/cyclone/sickle/Scope.c @@ -0,0 +1,1043 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER cache gui commands */ +/* LATER think about resizing scheme. Currently mouse events are not bound + to any part of Scope~'s 'widget' as such, but to a special item, which is + created only for a selected Scope~. For the other scheme see the 'comment' + class (no indicator there, though -- neither a handle, nor a pointer change). + One way or the other, the traffic from the gui layer should be kept possibly + low, at least in run-mode. */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "common/grow.h" +#include "unstable/forky.h" +#include "sickle/sic.h" + +//#define SCOPE_DEBUG + +/* these are powers of 2 + margins */ +#define SCOPE_DEFWIDTH 130 /* CHECKED */ +#define SCOPE_MINWIDTH 66 +#define SCOPE_DEFHEIGHT 130 /* CHECKED */ +#define SCOPE_MINHEIGHT 34 +#define SCOPE_DEFPERIOD 256 +#define SCOPE_MINPERIOD 2 +#define SCOPE_MAXPERIOD 8092 +#define SCOPE_DEFBUFSIZE 128 +#define SCOPE_MINBUFSIZE 8 +#define SCOPE_MAXBUFSIZE 800 /* LATER rethink */ +#define SCOPE_WARNBUFSIZE 256 +#define SCOPE_DEFMINVAL -1. +#define SCOPE_DEFMAXVAL 1. +#define SCOPE_DEFDELAY 0 +#define SCOPE_MINDELAY 0 +#define SCOPE_TRIGLINEMODE 0 +#define SCOPE_TRIGUPMODE 1 +#define SCOPE_TRIGDOWNMODE 2 +#define SCOPE_DEFTRIGMODE SCOPE_TRIGLINEMODE +#define SCOPE_MINTRIGMODE SCOPE_TRIGLINEMODE +#define SCOPE_MAXTRIGMODE SCOPE_TRIGDOWNMODE +#define SCOPE_DEFTRIGLEVEL 0. +#define SCOPE_MINCOLOR 0 +#define SCOPE_MAXCOLOR 255 +#define SCOPE_DEFFGRED 102 +#define SCOPE_DEFFGGREEN 255 +#define SCOPE_DEFFGBLUE 51 +#define SCOPE_DEFBGRED 135 +#define SCOPE_DEFBGGREEN 135 +#define SCOPE_DEFBGBLUE 135 +#define SCOPE_SELCOLOR "#8080ff" /* a bit lighter shade of blue */ +#define SCOPE_FGWIDTH 0.7 /* line width is float */ +#define SCOPE_GRIDWIDTH 0.9 +#define SCOPE_SELBDWIDTH 3.0 +#define SCOPEHANDLE_WIDTH 10 /* item size is int */ +#define SCOPEHANDLE_HEIGHT 10 +/* these are performance-related hacks, LATER investigate */ +#define SCOPE_GUICHUNKMONO 16 +#define SCOPE_GUICHUNKXY 32 + +typedef struct _scope +{ + t_sic x_sic; + t_glist *x_glist; + t_canvas *x_canvas; /* also an 'isvised' flag */ + char x_tag[64]; + char x_fgtag[64]; + char x_bgtag[64]; + char x_gridtag[64]; + int x_width; + int x_height; + float x_minval; + float x_maxval; + int x_delay; + int x_trigmode; + float x_triglevel; + unsigned char x_fgred; + unsigned char x_fggreen; + unsigned char x_fgblue; + unsigned char x_bgred; + unsigned char x_bggreen; + unsigned char x_bgblue; + int x_xymode; + float *x_xbuffer; + float *x_ybuffer; + float x_xbufini[SCOPE_DEFBUFSIZE]; + float x_ybufini[SCOPE_DEFBUFSIZE]; + int x_allocsize; + int x_bufsize; + int x_bufphase; + int x_period; + int x_phase; + int x_precount; + int x_retrigger; + float x_ksr; + float x_currx; + float x_curry; + float x_trigx; + int x_frozen; + t_clock *x_clock; + t_pd *x_handle; +} t_scope; + +typedef struct _scopehandle +{ + t_pd h_pd; + t_scope *h_master; + t_symbol *h_bindsym; + char h_pathname[64]; + char h_outlinetag[64]; + int h_dragon; + int h_dragx; + int h_dragy; +} t_scopehandle; + +static t_class *scope_class; +static t_class *scopehandle_class; + +static void scope_clear(t_scope *x, int withdelay) +{ + x->x_bufphase = 0; + x->x_phase = 0; + x->x_precount = (withdelay ? (int)(x->x_delay * x->x_ksr) : 0); + /* CHECKED delay does not matter (refman is wrong) */ + x->x_retrigger = (x->x_trigmode != SCOPE_TRIGLINEMODE); + x->x_trigx = x->x_triglevel; +} + +static t_int *scope_monoperform(t_int *w) +{ + t_scope *x = (t_scope *)(w[1]); + int bufphase = x->x_bufphase; + int bufsize = x->x_bufsize; + if (bufphase < bufsize) + { + int nblock = (int)(w[2]); + if (x->x_precount >= nblock) + x->x_precount -= nblock; + else + { + t_float *in = (t_float *)(w[3]); + int phase = x->x_phase; + int period = x->x_period; + float *bp1 = x->x_xbuffer + bufphase; + float *bp2 = x->x_ybuffer + bufphase; + float currx = x->x_currx; + if (x->x_precount > 0) + { + nblock -= x->x_precount; + in += x->x_precount; + x->x_precount = 0; + } + while (x->x_retrigger) + { + float triglevel = x->x_triglevel; + if (x->x_trigmode == SCOPE_TRIGUPMODE) + { + if (x->x_trigx < triglevel) + { + while (nblock--) if (*in++ >= triglevel) + { + x->x_retrigger = 0; + break; + } + } + else while (nblock--) if (*in++ < triglevel) + { + x->x_trigx = triglevel - 1.; + break; + } + } + else + { + if (x->x_trigx > triglevel) + { + while (nblock--) if (*in++ <= triglevel) + { + x->x_retrigger = 0; + break; + } + } + else while (nblock--) if (*in++ > triglevel) + { + x->x_trigx = triglevel + 1.; + break; + } + } + if (nblock <= 0) + return (w + 4); + } + while (nblock--) + { + if (phase) + { + float f = *in++; + /* CHECKED */ + if ((currx < 0 && (f < currx || f > -currx)) || + (currx > 0 && (f > currx || f < -currx))) + currx = f; + } + else currx = *in++; + if (currx != currx) + currx = 0.; /* CHECKED NaNs bashed to zeros */ + if (++phase == period) + { + phase = 0; + if (++bufphase == bufsize) + { + *bp1 = *bp2 = currx; + clock_delay(x->x_clock, 0); + break; + } + else *bp1++ = *bp2++ = currx; + } + } + x->x_currx = currx; + x->x_bufphase = bufphase; + x->x_phase = phase; + } + } + return (w + 4); +} + +static t_int *scope_xyperform(t_int *w) +{ + t_scope *x = (t_scope *)(w[1]); + int bufphase = x->x_bufphase; + int bufsize = x->x_bufsize; + if (bufphase < bufsize) + { + int nblock = (int)(w[2]); + if (x->x_precount >= nblock) + x->x_precount -= nblock; + else + { + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + int phase = x->x_phase; + int period = x->x_period; + float freq = 1. / period; + float *bp1 = x->x_xbuffer + bufphase; + float *bp2 = x->x_ybuffer + bufphase; + float currx = x->x_currx; + float curry = x->x_curry; + if (x->x_precount > 0) + { + nblock -= x->x_precount; + in1 += x->x_precount; + in2 += x->x_precount; + x->x_precount = 0; + } + if (x->x_retrigger) + { + /* CHECKME and FIXME */ + x->x_retrigger = 0; + } + while (nblock--) + { + if (phase) + { + /* CHECKME */ + currx += *in1++; + curry += *in2++; + } + else + { + currx = *in1++; + curry = *in2++; + } + if (currx != currx) + currx = 0.; /* CHECKME NaNs bashed to zeros */ + if (curry != curry) + curry = 0.; /* CHECKME NaNs bashed to zeros */ + if (++phase == period) + { + phase = 0; + if (++bufphase == bufsize) + { + *bp1 = currx * freq; + *bp2 = curry * freq; + clock_delay(x->x_clock, 0); + break; + } + else + { + *bp1++ = currx * freq; + *bp2++ = curry * freq; + } + } + } + x->x_currx = currx; + x->x_curry = curry; + x->x_bufphase = bufphase; + x->x_phase = phase; + } + } + return (w + 5); +} + +static void scope_setxymode(t_scope *x, int xymode); + +static void scope_dsp(t_scope *x, t_signal **sp) +{ + x->x_ksr = sp[0]->s_sr * 0.001; + scope_setxymode(x, + forky_hasfeeders((t_object *)x, x->x_glist, 1, &s_signal)); + if (x->x_xymode) + dsp_add(scope_xyperform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + else + dsp_add(scope_monoperform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static t_canvas *scope_getcanvas(t_scope *x, t_glist *glist) +{ + if (glist != x->x_glist) + { + bug("scope_getcanvas"); + x->x_glist = glist; + } + return (x->x_canvas = glist_getcanvas(glist)); +} + +/* answers the question: ``can we draw and where to?'' */ +static t_canvas *scope_isvisible(t_scope *x) +{ + return (glist_isvisible(x->x_glist) ? x->x_canvas : 0); +} + +static void scope_period(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float period = (s ? x->x_period : SCOPE_DEFPERIOD); + int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 2), ac, av, &period, + SCOPE_MINPERIOD, SCOPE_MAXPERIOD, + /* LATER rethink warning rules */ + (s ? LOUD_CLIP : LOUD_CLIP | LOUD_WARN), + (s ? 0 : LOUD_WARN), "samples per element"); + if (!s || result == LOUD_ARGOK || result == LOUD_ARGOVER) + { + x->x_period = (int)period; + scope_clear(x, 0); + } +} + +static void scope_float(t_scope *x, t_float f) +{ + t_atom at; + SETFLOAT(&at, f); + scope_period(x, &s_float, 1, &at); +} + +static void scope_bufsize(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float bufsize = (s ? x->x_bufsize : SCOPE_DEFBUFSIZE); + int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 4), ac, av, &bufsize, + SCOPE_MINBUFSIZE, SCOPE_WARNBUFSIZE, + /* LATER rethink warning rules */ + (s ? LOUD_CLIP : LOUD_CLIP | LOUD_WARN), + (s ? 0 : LOUD_WARN), "display elements"); + if (result == LOUD_ARGOVER) + { + bufsize = (s ? x->x_bufsize : SCOPE_DEFBUFSIZE); + result = loud_floatarg(*(t_pd *)x, (s ? 0 : 4), ac, av, &bufsize, + 0, SCOPE_MAXBUFSIZE, 0, LOUD_CLIP | LOUD_WARN, + "display elements"); + } + if (!s) + { + x->x_allocsize = SCOPE_DEFBUFSIZE; + x->x_bufsize = 0; + x->x_xbuffer = x->x_xbufini; + x->x_ybuffer = x->x_ybufini; + } + if (!s || result == LOUD_ARGOK) + { + int newsize = (int)bufsize; + if (newsize > x->x_allocsize) + { + int nrequested = newsize; + int allocsize = x->x_allocsize; + int oldsize = x->x_bufsize; + x->x_xbuffer = grow_withdata(&nrequested, &oldsize, + &allocsize, x->x_xbuffer, + SCOPE_DEFBUFSIZE, x->x_xbufini, + sizeof(*x->x_xbuffer)); + if (nrequested == newsize) + { + allocsize = x->x_allocsize; + oldsize = x->x_bufsize; + x->x_ybuffer = grow_withdata(&nrequested, &oldsize, + &allocsize, x->x_ybuffer, + SCOPE_DEFBUFSIZE, x->x_ybufini, + sizeof(*x->x_ybuffer)); + } + if (nrequested == newsize) + { + x->x_allocsize = allocsize; + x->x_bufsize = newsize; + } + else + { + if (x->x_xbuffer != x->x_xbufini) + freebytes(x->x_xbuffer, + x->x_allocsize * sizeof(*x->x_xbuffer)); + if (x->x_ybuffer != x->x_ybufini) + freebytes(x->x_ybuffer, + x->x_allocsize * sizeof(*x->x_ybuffer)); + x->x_allocsize = SCOPE_DEFBUFSIZE; + x->x_bufsize = SCOPE_DEFBUFSIZE; + x->x_xbuffer = x->x_xbufini; + x->x_ybuffer = x->x_ybufini; + } + } + else x->x_bufsize = newsize; + scope_clear(x, 0); + } +} + +static void scope_range(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float minval = (s ? x->x_minval : SCOPE_DEFMINVAL); + t_float maxval = (s ? x->x_maxval : SCOPE_DEFMAXVAL); + loud_floatarg(*(t_pd *)x, (s ? 0 : 5), ac, av, &minval, 0, 0, 0, 0, 0); + loud_floatarg(*(t_pd *)x, (s ? 1 : 6), ac, av, &maxval, 0, 0, 0, 0, 0); + /* CHECKME swapping, ignoring if equal */ + if (minval < maxval) + { + x->x_minval = minval; + x->x_maxval = maxval; + } + else if (minval > maxval) + { + x->x_minval = maxval; + x->x_maxval = minval; + } + else if (!s) + { + x->x_minval = SCOPE_DEFMINVAL; + x->x_maxval = SCOPE_DEFMAXVAL; + } +} + +static void scope_delay(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float delay = (s ? x->x_delay : SCOPE_DEFDELAY); + int result = loud_floatarg(*(t_pd *)x, (s ? 0 : 7), ac, av, &delay, + SCOPE_MINDELAY, 0, + LOUD_CLIP | LOUD_WARN, 0, "delay"); + if (!s || result == LOUD_ARGOK) + x->x_delay = delay; +} + +static void scope_trigger(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float trigmode = (s ? x->x_trigmode : SCOPE_DEFTRIGMODE); + loud_floatarg(*(t_pd *)x, (s ? 0 : 9), ac, av, &trigmode, + SCOPE_MINTRIGMODE, SCOPE_MAXTRIGMODE, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, + "trigger mode"); + x->x_trigmode = (int)trigmode; + if (x->x_trigmode == SCOPE_TRIGLINEMODE) + x->x_retrigger = 0; +} + +static void scope_triglevel(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float triglevel = (s ? x->x_triglevel : SCOPE_DEFTRIGLEVEL); + loud_floatarg(*(t_pd *)x, (s ? 0 : 10), ac, av, &triglevel, 0, 0, 0, 0, 0); + x->x_triglevel = triglevel; +} + +static void scope_frgb(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float fgred = (s ? x->x_fgred : SCOPE_DEFFGRED); + t_float fggreen = (s ? x->x_fggreen : SCOPE_DEFFGGREEN); + t_float fgblue = (s ? x->x_fgblue : SCOPE_DEFFGBLUE); + t_canvas *cv; + loud_floatarg(*(t_pd *)x, (s ? 0 : 11), ac, av, &fgred, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + loud_floatarg(*(t_pd *)x, (s ? 1 : 12), ac, av, &fggreen, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + loud_floatarg(*(t_pd *)x, (s ? 2 : 13), ac, av, &fgblue, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + x->x_fgred = (int)fgred; + x->x_fggreen = (int)fggreen; + x->x_fgblue = (int)fgblue; + if (cv = scope_isvisible(x)) + sys_vgui(".x%x.c itemconfigure %s -fill #%2.2x%2.2x%2.2x\n", + cv, x->x_fgtag, x->x_fgred, x->x_fggreen, x->x_fgblue); +} + +static void scope_brgb(t_scope *x, t_symbol *s, int ac, t_atom *av) +{ + t_float bgred = (s ? x->x_bgred : SCOPE_DEFBGRED); + t_float bggreen = (s ? x->x_bggreen : SCOPE_DEFBGGREEN); + t_float bgblue = (s ? x->x_bgblue : SCOPE_DEFBGBLUE); + t_canvas *cv; + loud_floatarg(*(t_pd *)x, (s ? 0 : 14), ac, av, &bgred, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + loud_floatarg(*(t_pd *)x, (s ? 1 : 15), ac, av, &bggreen, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + loud_floatarg(*(t_pd *)x, (s ? 2 : 16), ac, av, &bgblue, + SCOPE_MINCOLOR, SCOPE_MAXCOLOR, + LOUD_CLIP | LOUD_WARN, LOUD_CLIP | LOUD_WARN, "color"); + x->x_bgred = (int)bgred; + x->x_bggreen = (int)bggreen; + x->x_bgblue = (int)bgblue; + if (cv = scope_isvisible(x)) + sys_vgui(".x%x.c itemconfigure %s -fill #%2.2x%2.2x%2.2x\n", + cv, x->x_bgtag, x->x_bgred, x->x_bggreen, x->x_bgblue); +} + +static void scope_getrect(t_gobj *z, t_glist *glist, + int *xp1, int *yp1, int *xp2, int *yp2) +{ + t_scope *x = (t_scope *)z; + float x1, y1, x2, y2; + x1 = text_xpix((t_text *)x, glist); + y1 = text_ypix((t_text *)x, glist); + x2 = x1 + x->x_width; + y2 = y1 + x->x_height; + *xp1 = x1; + *yp1 = y1; + *xp2 = x2; + *yp2 = y2; +} + +static void scope_displace(t_gobj *z, t_glist *glist, int dx, int dy) +{ + t_scope *x = (t_scope *)z; + t_text *t = (t_text *)z; + t->te_xpix += dx; + t->te_ypix += dy; + if (glist_isvisible(glist)) + { + t_canvas *cv = scope_getcanvas(x, glist); + sys_vgui(".x%x.c move %s %d %d\n", cv, x->x_tag, dx, dy); + canvas_fixlinesfor(cv, t); + } +} + +static void scope_select(t_gobj *z, t_glist *glist, int state) +{ + t_scope *x = (t_scope *)z; + t_canvas *cv = scope_getcanvas(x, glist); + t_scopehandle *sh = (t_scopehandle *)x->x_handle; + if (state) + { + int x1, y1, x2, y2; + scope_getrect(z, glist, &x1, &y1, &x2, &y2); + + sys_vgui(".x%x.c itemconfigure %s -outline blue -width %f -fill %s\n", + cv, x->x_bgtag, SCOPE_SELBDWIDTH, SCOPE_SELCOLOR); + + sys_vgui("canvas %s -width %d -height %d -bg #fedc00 -bd 0\n", + sh->h_pathname, SCOPEHANDLE_WIDTH, SCOPEHANDLE_HEIGHT); + sys_vgui(".x%x.c create window %f %f -anchor nw\ + -width %d -height %d -window %s -tags %s\n", + cv, x2 - (SCOPEHANDLE_WIDTH - SCOPE_SELBDWIDTH), + y2 - (SCOPEHANDLE_HEIGHT - SCOPE_SELBDWIDTH), + SCOPEHANDLE_WIDTH, SCOPEHANDLE_HEIGHT, + sh->h_pathname, x->x_tag); + sys_vgui("bind %s <Button> {pd [concat %s _click 1 \\;]}\n", + sh->h_pathname, sh->h_bindsym->s_name); + sys_vgui("bind %s <ButtonRelease> {pd [concat %s _click 0 \\;]}\n", + sh->h_pathname, sh->h_bindsym->s_name); + sys_vgui("bind %s <Motion> {pd [concat %s _motion %%x %%y \\;]}\n", + sh->h_pathname, sh->h_bindsym->s_name); + } + else + { + sys_vgui(".x%x.c itemconfigure %s -outline black -width %f\ + -fill #%2.2x%2.2x%2.2x\n", cv, x->x_bgtag, SCOPE_GRIDWIDTH, + x->x_bgred, x->x_bggreen, x->x_bgblue); + sys_vgui("destroy %s\n", sh->h_pathname); + } +} + +static void scope_delete(t_gobj *z, t_glist *glist) +{ + canvas_deletelinesfor(glist, (t_text *)z); +} + +static void scope_drawfgmono(t_scope *x, t_canvas *cv, + int x1, int y1, int x2, int y2) +{ + int i; + float dx, dy, xx, yy, sc; + float *bp; + dx = (float)(x2 - x1) / (float)x->x_bufsize; + sc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval); + sys_vgui(".x%x.c create line \\\n", cv); + for (i = 0, xx = x1, bp = x->x_xbuffer; + i < x->x_bufsize; i++, xx += dx, bp++) + { + yy = (y2 - 1) - sc * (*bp - x->x_minval); +#ifndef SCOPE_DEBUG + if (yy > y2) yy = y2; else if (yy < y1) yy = y1; +#endif + sys_vgui("%d %d \\\n", (int)xx, (int)yy); + } + sys_vgui("-fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n", + x->x_fgred, x->x_fggreen, x->x_fgblue, + SCOPE_FGWIDTH, x->x_fgtag, x->x_tag); + + /* margin lines: masking overflows, so that they appear as gaps, + rather than clipped signal values, LATER rethink */ + sys_vgui(".x%x.c create line %d %d %d %d\ + -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n", + cv, x1, y1, x2, y1, x->x_bgred, x->x_bggreen, x->x_bgblue, + 1., x->x_fgtag, x->x_tag); + sys_vgui(".x%x.c create line %d %d %d %d\ + -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n", + cv, x1, y2, x2, y2, x->x_bgred, x->x_bggreen, x->x_bgblue, + 1., x->x_fgtag, x->x_tag); +} + +static void scope_drawfgxy(t_scope *x, t_canvas *cv, + int x1, int y1, int x2, int y2) +{ + int nleft = x->x_bufsize; + float *xbp = x->x_xbuffer, *ybp = x->x_ybuffer; + char chunk[200 * SCOPE_GUICHUNKXY]; /* LATER estimate */ + char *chunkp = chunk; + char cmd1[64], cmd2[64]; + float xx, yy, xsc, ysc; + xx = yy = 0; + /* subtract 1-pixel margins, see below */ + xsc = ((float)x->x_width - 2.) / (float)(x->x_maxval - x->x_minval); + ysc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval); + sprintf(cmd1, ".x%x.c create line", (int)cv); + sprintf(cmd2, "-fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n ", + x->x_fgred, x->x_fggreen, x->x_fgblue, + SCOPE_FGWIDTH, x->x_fgtag, x->x_tag); + while (nleft > SCOPE_GUICHUNKXY) + { + int i = SCOPE_GUICHUNKXY; + while (i--) + { + float oldx = xx, oldy = yy, dx, dy; + xx = x1 + xsc * (*xbp++ - x->x_minval); + yy = y2 - ysc * (*ybp++ - x->x_minval); + /* using 1-pixel margins */ + dx = (xx > oldx ? 1. : -1.); + dy = (yy > oldy ? 1. : -1.); +#ifndef SCOPE_DEBUG + if (xx < x1 || xx > x2 || yy < y1 || yy > y2) + continue; +#endif + sprintf(chunkp, "%s %d %d %d %d %s", cmd1, + (int)(xx - dx), (int)(yy - dy), + (int)(xx + dx), (int)(yy + dy), cmd2); + chunkp += strlen(chunkp); + } + if (chunkp > chunk) + sys_gui(chunk); + chunkp = chunk; + nleft -= SCOPE_GUICHUNKXY; + } + while (nleft--) + { + float oldx = xx, oldy = yy, dx, dy; + xx = x1 + xsc * (*xbp++ - x->x_minval); + yy = y2 - ysc * (*ybp++ - x->x_minval); + /* using 1-pixel margins */ + dx = (xx > oldx ? 1. : -1.); + dy = (yy > oldy ? 1. : -1.); +#ifndef SCOPE_DEBUG + if (xx < x1 || xx > x2 || yy < y1 || yy > y2) + continue; +#endif + sprintf(chunkp, "%s %d %d %d %d %s", cmd1, + (int)(xx - dx), (int)(yy - dy), + (int)(xx + dx), (int)(yy + dy), cmd2); + chunkp += strlen(chunkp); + } + if (chunkp > chunk) + sys_gui(chunk); +} + +static void scope_drawbg(t_scope *x, t_canvas *cv, + int x1, int y1, int x2, int y2) +{ + int i; + float dx, dy, xx, yy; + dx = (x2 - x1) * 0.125; + dy = (y2 - y1) * 0.25; + sys_vgui(".x%x.c create rectangle %d %d %d %d\ + -fill #%2.2x%2.2x%2.2x -width %f -tags {%s %s}\n", + cv, x1, y1, x2, y2, + x->x_bgred, x->x_bggreen, x->x_bgblue, + SCOPE_GRIDWIDTH, x->x_bgtag, x->x_tag); + for (i = 0, xx = x1 + dx; i < 7; i++, xx += dx) + sys_vgui(".x%x.c create line %f %d %f %d\ + -width %f -tags {%s %s}\n", cv, xx, y1, xx, y2, + SCOPE_GRIDWIDTH, x->x_gridtag, x->x_tag); + for (i = 0, yy = y1 + dy; i < 3; i++, yy += dy) + sys_vgui(".x%x.c create line %d %f %d %f\ + -width %f -tags {%s %s}\n", cv, x1, yy, x2, yy, + SCOPE_GRIDWIDTH, x->x_gridtag, x->x_tag); +} + +static void scope_drawmono(t_scope *x, t_canvas *cv) +{ + int x1, y1, x2, y2; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + scope_drawbg(x, cv, x1, y1, x2, y2); + scope_drawfgmono(x, cv, x1, y1, x2, y2); +} + +static void scope_redrawmono(t_scope *x, t_canvas *cv) +{ + int nleft = x->x_bufsize; + float *bp = x->x_xbuffer; + char chunk[32 * SCOPE_GUICHUNKMONO]; /* LATER estimate */ + char *chunkp = chunk; + int x1, y1, x2, y2; + float dx, dy, xx, yy, sc; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + dx = (float)(x2 - x1) / (float)x->x_bufsize; + sc = ((float)x->x_height - 2.) / (float)(x->x_maxval - x->x_minval); + xx = x1; + sys_vgui(".x%x.c coords %s \\\n", cv, x->x_fgtag); + while (nleft > SCOPE_GUICHUNKMONO) + { + int i = SCOPE_GUICHUNKMONO; + while (i--) + { + yy = (y2 - 1) - sc * (*bp++ - x->x_minval); +#ifndef SCOPE_DEBUG + if (yy > y2) yy = y2; else if (yy < y1) yy = y1; +#endif + sprintf(chunkp, "%d %d ", (int)xx, (int)yy); + chunkp += strlen(chunkp); + xx += dx; + } + strcpy(chunkp, "\\\n"); + sys_gui(chunk); + chunkp = chunk; + nleft -= SCOPE_GUICHUNKMONO; + } + while (nleft--) + { + yy = (y2 - 1) - sc * (*bp++ - x->x_minval); +#ifndef SCOPE_DEBUG + if (yy > y2) yy = y2; else if (yy < y1) yy = y1; +#endif + sprintf(chunkp, "%d %d ", (int)xx, (int)yy); + chunkp += strlen(chunkp); + xx += dx; + } + strcpy(chunkp, "\n"); + sys_gui(chunk); +} + +static void scope_drawxy(t_scope *x, t_canvas *cv) +{ + int x1, y1, x2, y2; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + scope_drawbg(x, cv, x1, y1, x2, y2); + scope_drawfgxy(x, cv, x1, y1, x2, y2); +} + +static void scope_redrawxy(t_scope *x, t_canvas *cv) +{ + int x1, y1, x2, y2; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + sys_vgui(".x%x.c delete %s\n", cv, x->x_fgtag); + scope_drawfgxy(x, cv, x1, y1, x2, y2); +} + +static void scope_revis(t_scope *x, t_canvas *cv) +{ + sys_vgui(".x%x.c delete %s\n", cv, x->x_tag); + if (x->x_xymode) + scope_drawxy(x, cv); + else + scope_drawmono(x, cv); +} + +static void scope_vis(t_gobj *z, t_glist *glist, int vis) +{ + t_scope *x = (t_scope *)z; + t_text *t = (t_text *)z; + t_canvas *cv = scope_getcanvas(x, glist); + if (vis) + { + t_scopehandle *sh = (t_scopehandle *)x->x_handle; +#ifndef PD_MINOR_VERSION + rtext_new(glist, t, glist->gl_editor->e_rtext, 0); +#endif + sprintf(sh->h_pathname, ".x%x.h%x", (int)cv, (int)sh); + if (x->x_xymode) + scope_drawxy(x, cv); + else + scope_drawmono(x, cv); + } + else + { +#ifndef PD_MINOR_VERSION + t_rtext *rt = glist_findrtext(glist, t); + if (rt) rtext_free(rt); +#endif + sys_vgui(".x%x.c delete %s\n", cv, x->x_tag); + x->x_canvas = 0; + } +} + +static int scope_click(t_gobj *z, t_glist *glist, + int xpix, int ypix, int shift, int alt, int dbl, + int doit) +{ + t_scope *x = (t_scope *)z; + x->x_frozen = doit; + return (CURSOR_RUNMODE_CLICKME); +} + +/* CHECKED there is only one copy of state variables, + the same, whether modified with messages, or in the inspector */ +static void scope_save(t_gobj *z, t_binbuf *b) +{ + t_scope *x = (t_scope *)z; + t_text *t = (t_text *)x; + binbuf_addv(b, "ssiisiiiiiffififiiiiiii;", gensym("#X"), gensym("obj"), + (int)t->te_xpix, (int)t->te_ypix, + gensym("Scope~"), + x->x_width, x->x_height, x->x_period, 3, x->x_bufsize, + x->x_minval, x->x_maxval, x->x_delay, 0., + x->x_trigmode, x->x_triglevel, + x->x_fgred, x->x_fggreen, x->x_fgblue, + x->x_bgred, x->x_bggreen, x->x_bgblue, 0); +} + +static t_widgetbehavior scope_widgetbehavior = +{ + scope_getrect, + scope_displace, + scope_select, + 0, + scope_delete, + scope_vis, + scope_click, + scope_save, + 0 +}; + +static void scope_setxymode(t_scope *x, int xymode) +{ + if (xymode != x->x_xymode) + { + t_canvas *cv; + if (cv = scope_isvisible(x)) + { + sys_vgui(".x%x.c delete %s\n", cv, x->x_fgtag); + if (!xymode) + { + int x1, y1, x2, y2; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + scope_drawfgmono(x, cv, x1, y1, x2, y2); + } + } + x->x_xymode = xymode; + scope_clear(x, 0); + } +} + +static void scope_tick(t_scope *x) +{ + t_canvas *cv; + if (!x->x_frozen && (cv = scope_isvisible(x))) + { + if (x->x_xymode) + scope_redrawxy(x, cv); + else + scope_redrawmono(x, cv); + } + scope_clear(x, 1); +} + +static void scopehandle__clickhook(t_scopehandle *sh, t_floatarg f) +{ + int newstate = (int)f; + if (sh->h_dragon && newstate == 0) + { + t_scope *x = sh->h_master; + t_canvas *cv; + x->x_width += sh->h_dragx; + x->x_height += sh->h_dragy; + if (cv = scope_isvisible(x)) + { + sys_vgui(".x%x.c delete %s\n", cv, sh->h_outlinetag); + scope_revis(x, cv); + sys_vgui("destroy %s\n", sh->h_pathname); + scope_select((t_gobj *)x, x->x_glist, 1); + canvas_fixlinesfor(x->x_glist, (t_text *)x); /* 2nd inlet */ + } + } + else if (!sh->h_dragon && newstate) + { + t_scope *x = sh->h_master; + t_canvas *cv; + if (cv = scope_isvisible(x)) + { + int x1, y1, x2, y2; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + sys_vgui("lower %s\n", sh->h_pathname); + sys_vgui(".x%x.c create rectangle %d %d %d %d\ + -outline blue -width %f -tags %s\n", + cv, x1, y1, x2, y2, SCOPE_SELBDWIDTH, sh->h_outlinetag); + } + sh->h_dragx = 0; + sh->h_dragy = 0; + } + sh->h_dragon = newstate; +} + +static void scopehandle__motionhook(t_scopehandle *sh, + t_floatarg f1, t_floatarg f2) +{ + if (sh->h_dragon) + { + t_scope *x = sh->h_master; + int dx = (int)f1, dy = (int)f2; + int x1, y1, x2, y2, newx, newy; + scope_getrect((t_gobj *)x, x->x_glist, &x1, &y1, &x2, &y2); + newx = x2 + dx; + newy = y2 + dy; + if (newx > x1 + SCOPE_MINWIDTH && newy > y1 + SCOPE_MINHEIGHT) + { + t_canvas *cv; + if (cv = scope_isvisible(x)) + sys_vgui(".x%x.c coords %s %d %d %d %d\n", + cv, sh->h_outlinetag, x1, y1, newx, newy); + sh->h_dragx = dx; + sh->h_dragy = dy; + } + } +} + +static void scope_free(t_scope *x) +{ + if (x->x_clock) clock_free(x->x_clock); + if (x->x_xbuffer != x->x_xbufini) + freebytes(x->x_xbuffer, x->x_allocsize * sizeof(*x->x_xbuffer)); + if (x->x_ybuffer != x->x_ybufini) + freebytes(x->x_ybuffer, x->x_allocsize * sizeof(*x->x_ybuffer)); + if (x->x_handle) + { + pd_unbind(x->x_handle, ((t_scopehandle *)x->x_handle)->h_bindsym); + pd_free(x->x_handle); + } +} + +static void *scope_new(t_symbol *s, int ac, t_atom *av) +{ + t_scope *x = (t_scope *)pd_new(scope_class); + t_scopehandle *sh; + t_float width = SCOPE_DEFWIDTH; + t_float height = SCOPE_DEFHEIGHT; + char buf[64]; + x->x_glist = canvas_getcurrent(); + x->x_canvas = 0; + loud_floatarg(*(t_pd *)x, 0, ac, av, &width, + SCOPE_MINWIDTH, 0, + LOUD_CLIP | LOUD_WARN, 0, "width"); + x->x_width = (int)width; + loud_floatarg(*(t_pd *)x, 1, ac, av, &height, + SCOPE_MINHEIGHT, 0, + LOUD_CLIP | LOUD_WARN, 0, "height"); + x->x_height = (int)height; + scope_period(x, 0, ac, av); + /* CHECKME 6th argument (default 3 for mono, 1 for xy */ + scope_bufsize(x, 0, ac, av); + scope_range(x, 0, ac, av); + scope_delay(x, 0, ac, av); + /* CHECKME 11th argument (default 0.) */ + scope_trigger(x, 0, ac, av); + scope_triglevel(x, 0, ac, av); + scope_frgb(x, 0, ac, av); + scope_brgb(x, 0, ac, av); + /* CHECKME last argument (default 0) */ + + sprintf(x->x_tag, "all%x", (int)x); + sprintf(x->x_bgtag, "bg%x", (int)x); + sprintf(x->x_gridtag, "gr%x", (int)x); + sprintf(x->x_fgtag, "fg%x", (int)x); + x->x_xymode = 0; + x->x_ksr = sys_getsr() * 0.001; /* redundant */ + x->x_frozen = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + x->x_clock = clock_new(x, (t_method)scope_tick); + scope_clear(x, 0); + + x->x_handle = pd_new(scopehandle_class); + sh = (t_scopehandle *)x->x_handle; + sh->h_master = x; + sprintf(buf, "_h%x", (int)sh); + pd_bind(x->x_handle, sh->h_bindsym = gensym(buf)); + sprintf(sh->h_outlinetag, "h%x", (int)sh); + sh->h_dragon = 0; + return (x); +} + +void Scope_tilde_setup(void) +{ + scope_class = class_new(gensym("Scope~"), + (t_newmethod)scope_new, + (t_method)scope_free, + sizeof(t_scope), 0, A_GIMME, 0); + sic_setup(scope_class, scope_dsp, scope_float); + class_addmethod(scope_class, (t_method)scope_bufsize, + gensym("bufsize"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_range, + gensym("range"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_delay, + gensym("delay"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_trigger, + gensym("trigger"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_triglevel, + gensym("triglevel"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_frgb, + gensym("frgb"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_brgb, + gensym("brgb"), A_GIMME, 0); + class_addmethod(scope_class, (t_method)scope_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + class_setwidget(scope_class, &scope_widgetbehavior); + scopehandle_class = class_new(gensym("_scopehandle"), 0, 0, + sizeof(t_scopehandle), CLASS_PD, 0); + class_addmethod(scopehandle_class, (t_method)scopehandle__clickhook, + gensym("_click"), A_FLOAT, 0); + class_addmethod(scopehandle_class, (t_method)scopehandle__motionhook, + gensym("_motion"), A_FLOAT, A_FLOAT, 0); +} diff --git a/cyclone/sickle/Snapshot.c b/cyclone/sickle/Snapshot.c new file mode 100644 index 0000000..7c7e974 --- /dev/null +++ b/cyclone/sickle/Snapshot.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +/* CHECKME for a fixed minimum deltime, if any (5ms for c74's metro) */ + +typedef struct _snapshot +{ + t_sic x_sic; + t_float x_value; + int x_rqoffset; /* requested */ + int x_offset; /* effective (truncated) */ + int x_stopped; + int x_on; /* !stopped && deltime > 0 */ + float x_deltime; + int x_npoints; + int x_nleft; + int x_nblock; + float x_ksr; + t_clock *x_clock; +} t_snapshot; + +static t_class *snapshot_class; + +static void snapshot_tick(t_snapshot *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void snapshot_bang(t_snapshot *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); +} + +static void snapshot_correct(t_snapshot *x) +{ + int wason = x->x_on; + x->x_offset = + (x->x_rqoffset < x->x_nblock ? x->x_rqoffset : x->x_nblock - 1); + x->x_npoints = x->x_deltime * x->x_ksr - x->x_nblock + x->x_offset; + if (x->x_on = (!x->x_stopped && x->x_deltime > 0.)) + { + if (!wason) x->x_nleft = x->x_offset; /* CHECKME */ + } + else if (wason) clock_unset(x->x_clock); +} + +static void snapshot_start(t_snapshot *x) +{ + x->x_stopped = 0; + if (!x->x_on && x->x_deltime > 0.) /* CHECKED no default */ + { + x->x_nleft = x->x_offset; /* CHECKME */ + x->x_on = 1; + } +} + +static void snapshot_stop(t_snapshot *x) +{ + x->x_stopped = 1; + if (x->x_on) + { + clock_unset(x->x_clock); + x->x_on = 0; + } +} + +static void snapshot_float(t_snapshot *x, t_float f) +{ + /* CHECKED nonzero/zero, CHECKED incompatible: int only (float ignored) */ + if (f != 0.) + snapshot_start(x); + else + snapshot_stop(x); +} + +static void snapshot_ft1(t_snapshot *x, t_floatarg f) +{ + x->x_deltime = (f > 0. ? f : 0.); /* CHECKED */ + /* CHECKED setting deltime to a positive value starts the clock + only if it was stopped by setting deltime to zero */ + snapshot_correct(x); +} + +static void snapshot_offset(t_snapshot *x, t_floatarg f) +{ + int i = (int)f; /* CHECKME */ + x->x_rqoffset = (i >= 0 ? i : 0); /* CHECKME */ + /* CHECKME if the change has an effect prior to next dsp_add call */ + snapshot_correct(x); +} + +static t_int *snapshot_perform(t_int *w) +{ + t_snapshot *x = (t_snapshot *)(w[1]); + t_float *in = (t_float *)(w[2]); + x->x_value = in[x->x_offset]; + if (x->x_on) + { + /* CHECKME nleft vs offset */ + if (x->x_nleft < x->x_nblock) + { + clock_delay(x->x_clock, 0); + x->x_nleft = x->x_npoints; + } + else x->x_nleft -= x->x_nblock; + } + return (w + 3); +} + +static void snapshot_dsp(t_snapshot *x, t_signal **sp) +{ + x->x_nblock = sp[0]->s_n; + x->x_ksr = sp[0]->s_sr * 0.001; + snapshot_correct(x); + x->x_nleft = x->x_offset; /* CHECKME */ + dsp_add(snapshot_perform, 2, x, sp[0]->s_vec); +} + +static void snapshot_free(t_snapshot *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *snapshot_new(t_floatarg f1, t_floatarg f2) +{ + t_snapshot *x = (t_snapshot *)pd_new(snapshot_class); + x->x_stopped = 0; /* CHECKED */ + x->x_on = 0; + x->x_value = 0; + x->x_nblock = 64; /* redundant */ + x->x_ksr = 44.1; /* redundant */ + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_clock = clock_new(x, (t_method)snapshot_tick); + snapshot_offset(x, f2); /* CHECKME (this is fixed at nblock-1 in Pd) */ + snapshot_ft1(x, f1); + return (x); +} + +void Snapshot_tilde_setup(void) +{ + snapshot_class = class_new(gensym("Snapshot~"), + (t_newmethod)snapshot_new, + (t_method)snapshot_free, + sizeof(t_snapshot), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(snapshot_class, snapshot_dsp, snapshot_float); + class_addbang(snapshot_class, snapshot_bang); + class_addmethod(snapshot_class, (t_method)snapshot_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(snapshot_class, (t_method)snapshot_offset, + gensym("offset"), A_FLOAT, 0); + class_addmethod(snapshot_class, (t_method)snapshot_start, + gensym("start"), 0); + class_addmethod(snapshot_class, (t_method)snapshot_stop, + gensym("stop"), 0); +} diff --git a/cyclone/sickle/abs.c b/cyclone/sickle/abs.c new file mode 100644 index 0000000..cde26a5 --- /dev/null +++ b/cyclone/sickle/abs.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef t_sic t_abs; +static t_class *abs_class; + +static t_int *abs_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = (f >= 0 ? f : -f); + } + return (w + 4); +} + +static void abs_dsp(t_abs *x, t_signal **sp) +{ + dsp_add(abs_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *abs_new(void) +{ + t_abs *x = (t_abs *)pd_new(abs_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void abs_tilde_setup(void) +{ + abs_class = class_new(gensym("abs~"), + (t_newmethod)abs_new, 0, + sizeof(t_abs), 0, 0); + sic_setup(abs_class, abs_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/acos.c b/cyclone/sickle/acos.c new file mode 100644 index 0000000..1dd5719 --- /dev/null +++ b/cyclone/sickle/acos.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define acosf acos +#endif + +typedef t_sic t_acos; +static t_class *acos_class; + +static t_int *acos_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = acosf(f); /* CHECKED no protection against NaNs */ + } + return (w + 4); +} + +static void acos_dsp(t_acos *x, t_signal **sp) +{ + dsp_add(acos_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *acos_new(void) +{ + t_acos *x = (t_acos *)pd_new(acos_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void acos_tilde_setup(void) +{ + acos_class = class_new(gensym("acos~"), + (t_newmethod)acos_new, 0, + sizeof(t_acos), 0, 0); + sic_setup(acos_class, acos_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/acosh.c b/cyclone/sickle/acosh.c new file mode 100644 index 0000000..392ad97 --- /dev/null +++ b/cyclone/sickle/acosh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* LATER ask about osx */ +#if defined(NT) || defined(MACOSX) +#define acoshf(x) (log(x + sqrt(x * x - 1))) +#endif + +typedef t_sic t_acosh; +static t_class *acosh_class; + +static t_int *acosh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = acoshf(f); /* CHECKME no protection against NaNs */ + } + return (w + 4); +} + +static void acosh_dsp(t_acosh *x, t_signal **sp) +{ + dsp_add(acosh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *acosh_new(void) +{ + t_acosh *x = (t_acosh *)pd_new(acosh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void acosh_tilde_setup(void) +{ + acosh_class = class_new(gensym("acosh~"), + (t_newmethod)acosh_new, 0, + sizeof(t_acosh), 0, 0); + sic_setup(acosh_class, acosh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/allpass.c b/cyclone/sickle/allpass.c new file mode 100644 index 0000000..761d0cc --- /dev/null +++ b/cyclone/sickle/allpass.c @@ -0,0 +1,153 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _allpass +{ + t_sic x_sic; + float x_sr; + float x_ksr; + t_float *x_buf; + int x_bufsize; /* as allocated */ + int x_maxsize; /* as used */ + float x_maxdelay; /* same in ms */ + int x_phase; /* writing head */ +} t_allpass; + +static t_class *allpass_class; + +/* maximum delay defaults to 50 ms (cycling has 10 ms here) */ +#define ALLPASS_DEFMAXDELAY 50.0 + +/* LATER choose the best way (compare with comb~) */ +#define ALLPASS_MAXFEEDBACK 0.999 + +static void allpass_clear(t_allpass *x) +{ + memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf)); + x->x_phase = 0; +} + +static void allpass_resize(t_allpass *x, int newsize) +{ + if (newsize > 0 && newsize != x->x_maxsize) + { + if (newsize > x->x_bufsize) + { + x->x_buf = resizebytes(x->x_buf, + x->x_bufsize * sizeof(*x->x_buf), + newsize * sizeof(*x->x_buf)); + /* LATER test for failure */ + x->x_bufsize = newsize; + } + x->x_maxsize = newsize; + } + allpass_clear(x); +} + +static t_int *allpass_perform(t_int *w) +{ + t_allpass *x = (t_allpass *)(w[1]); + int nblock = (int)(w[2]); + t_float *xin = (t_float *)(w[3]); + t_float *din = (t_float *)(w[4]); + t_float *gin = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + t_float *buf = x->x_buf; + int maxsize = x->x_maxsize; + int guardpoint = maxsize - 1; + float ksr = x->x_ksr; + int wph = x->x_phase; + while (nblock--) + { /* TDFII scheme */ + float xn = *xin++; + float delsize = ksr * *din++; + float gain = *gin++; + float yn; + float rph; /* reading head */ + if (gain < -ALLPASS_MAXFEEDBACK) gain = -ALLPASS_MAXFEEDBACK; + else if (gain > ALLPASS_MAXFEEDBACK) gain = ALLPASS_MAXFEEDBACK; + yn = -gain * xn; + if (delsize > 0) + { + int ndx; + float val; + rph = wph - (delsize > guardpoint ? guardpoint : delsize); + if (rph < 0) rph += guardpoint; + ndx = (int)rph; + val = buf[ndx]; + /* ``a cheezy linear interpolation'' ala msp, + (vd~ uses 4-point interpolation...) */ + yn += val + (buf[ndx+1] - val) * (rph - ndx); + } + *out++ = yn; + if (wph == guardpoint) + { + buf[wph] = *buf = xn + gain * yn; + wph = 1; + } + else buf[wph++] = xn + gain * yn; + } + x->x_phase = wph; + return (w + 7); +} + +static void allpass_dsp(t_allpass *x, t_signal **sp) +{ + float sr = sp[0]->s_sr; + if (sr != x->x_sr) + { + x->x_sr = sr; + x->x_ksr = sr * 0.001; + allpass_resize(x, x->x_ksr * x->x_maxdelay); + } + else allpass_clear(x); + dsp_add(allpass_perform, 6, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void *allpass_new(t_floatarg f1, t_floatarg f2, t_floatarg f3) +{ + t_allpass *x; + float maxdelay = (f1 > 0 ? f1 : ALLPASS_DEFMAXDELAY); + float sr = sys_getsr(); + float ksr = sr * 0.001; + int bufsize = ksr * maxdelay; + t_float *buf = (t_float *)getbytes(bufsize * sizeof(*buf)); + if (!buf) + return (0); + x = (t_allpass *)pd_new(allpass_class); + x->x_maxdelay = maxdelay; + x->x_sr = sr; + x->x_ksr = ksr; + x->x_bufsize = x->x_maxsize = bufsize; + x->x_buf = buf; + if (f2 < 0) f2 = 0; + if (f3 < -ALLPASS_MAXFEEDBACK) f3 = -ALLPASS_MAXFEEDBACK; + else if (f3 > ALLPASS_MAXFEEDBACK) f3 = ALLPASS_MAXFEEDBACK; + sic_newinlet((t_sic *)x, f2); + sic_newinlet((t_sic *)x, f3); + outlet_new((t_object *)x, &s_signal); + allpass_clear(x); + return (x); +} + +static void allpass_free(t_allpass *x) +{ + if (x->x_buf) freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf)); +} + +void allpass_tilde_setup(void) +{ + allpass_class = class_new(gensym("allpass~"), + (t_newmethod)allpass_new, + (t_method)allpass_free, + sizeof(t_allpass), 0, + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(allpass_class, allpass_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(allpass_class, (t_method)allpass_clear, gensym("clear"), 0); +} diff --git a/cyclone/sickle/allsickles.c b/cyclone/sickle/allsickles.c new file mode 100644 index 0000000..624a48d --- /dev/null +++ b/cyclone/sickle/allsickles.c @@ -0,0 +1,134 @@ +// Do not edit this file, run "make" instead. + +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +void Clip_tilde_setup(void); +void Line_tilde_setup(void); +void Scope_tilde_setup(void); +void Snapshot_tilde_setup(void); +void abs_tilde_setup(void); +void acos_tilde_setup(void); +void acosh_tilde_setup(void); +void allpass_tilde_setup(void); +void asin_tilde_setup(void); +void asinh_tilde_setup(void); +void atan_tilde_setup(void); +void atan2_tilde_setup(void); +void atanh_tilde_setup(void); +void average_tilde_setup(void); +void avg_tilde_setup(void); +void bitand_tilde_setup(void); +void bitnot_tilde_setup(void); +void bitor_tilde_setup(void); +void bitshift_tilde_setup(void); +void bitxor_tilde_setup(void); +void capture_tilde_setup(void); +void cartopol_tilde_setup(void); +void change_tilde_setup(void); +void click_tilde_setup(void); +void comb_tilde_setup(void); +void cosh_tilde_setup(void); +void cosx_tilde_setup(void); +void count_tilde_setup(void); +void cycle_tilde_setup(void); +void delay_tilde_setup(void); +void delta_tilde_setup(void); +void deltaclip_tilde_setup(void); +void edge_tilde_setup(void); +void frameaccum_tilde_setup(void); +void framedelta_tilde_setup(void); +void index_tilde_setup(void); +void kink_tilde_setup(void); +void linedrive_setup(void); +void log_tilde_setup(void); +void lookup_tilde_setup(void); +void minmax_tilde_setup(void); +void peakamp_tilde_setup(void); +void peek_tilde_setup(void); +void phasewrap_tilde_setup(void); +void play_tilde_setup(void); +void poltocar_tilde_setup(void); +void pow_tilde_setup(void); +void rampsmooth_tilde_setup(void); +void rand_tilde_setup(void); +void record_tilde_setup(void); +void sah_tilde_setup(void); +void sinh_tilde_setup(void); +void sinx_tilde_setup(void); +void slide_tilde_setup(void); +void spike_tilde_setup(void); +void tanh_tilde_setup(void); +void tanx_tilde_setup(void); +void train_tilde_setup(void); +void trapezoid_tilde_setup(void); +void triangle_tilde_setup(void); +void vectral_tilde_setup(void); +void wave_tilde_setup(void); + +void allsickles_setup(void) +{ + Clip_tilde_setup(); + Line_tilde_setup(); + Scope_tilde_setup(); + Snapshot_tilde_setup(); + abs_tilde_setup(); + acos_tilde_setup(); + acosh_tilde_setup(); + allpass_tilde_setup(); + asin_tilde_setup(); + asinh_tilde_setup(); + atan_tilde_setup(); + atan2_tilde_setup(); + atanh_tilde_setup(); + average_tilde_setup(); + avg_tilde_setup(); + bitand_tilde_setup(); + bitnot_tilde_setup(); + bitor_tilde_setup(); + bitshift_tilde_setup(); + bitxor_tilde_setup(); + capture_tilde_setup(); + cartopol_tilde_setup(); + change_tilde_setup(); + click_tilde_setup(); + comb_tilde_setup(); + cosh_tilde_setup(); + cosx_tilde_setup(); + count_tilde_setup(); + cycle_tilde_setup(); + delay_tilde_setup(); + delta_tilde_setup(); + deltaclip_tilde_setup(); + edge_tilde_setup(); + frameaccum_tilde_setup(); + framedelta_tilde_setup(); + index_tilde_setup(); + kink_tilde_setup(); + linedrive_setup(); + log_tilde_setup(); + lookup_tilde_setup(); + minmax_tilde_setup(); + peakamp_tilde_setup(); + peek_tilde_setup(); + phasewrap_tilde_setup(); + play_tilde_setup(); + poltocar_tilde_setup(); + pow_tilde_setup(); + rampsmooth_tilde_setup(); + rand_tilde_setup(); + record_tilde_setup(); + sah_tilde_setup(); + sinh_tilde_setup(); + sinx_tilde_setup(); + slide_tilde_setup(); + spike_tilde_setup(); + tanh_tilde_setup(); + tanx_tilde_setup(); + train_tilde_setup(); + trapezoid_tilde_setup(); + triangle_tilde_setup(); + vectral_tilde_setup(); + wave_tilde_setup(); +} diff --git a/cyclone/sickle/asin.c b/cyclone/sickle/asin.c new file mode 100644 index 0000000..05e5c28 --- /dev/null +++ b/cyclone/sickle/asin.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define asinf asin +#endif + +typedef t_sic t_asin; +static t_class *asin_class; + +static t_int *asin_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = asinf(f); /* CHECKME no protection against NaNs */ + } + return (w + 4); +} + +static void asin_dsp(t_asin *x, t_signal **sp) +{ + dsp_add(asin_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *asin_new(void) +{ + t_asin *x = (t_asin *)pd_new(asin_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void asin_tilde_setup(void) +{ + asin_class = class_new(gensym("asin~"), + (t_newmethod)asin_new, 0, + sizeof(t_asin), 0, 0); + sic_setup(asin_class, asin_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/asinh.c b/cyclone/sickle/asinh.c new file mode 100644 index 0000000..931cb1f --- /dev/null +++ b/cyclone/sickle/asinh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* LATER ask about osx */ +#if defined(NT) || defined(MACOSX) +#define asinhf(x) (log(x + sqrt(x * x + 1))) +#endif + +typedef t_sic t_asinh; +static t_class *asinh_class; + +static t_int *asinh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = asinhf(f); /* CHECKME no protection against NaNs */ + } + return (w + 4); +} + +static void asinh_dsp(t_asinh *x, t_signal **sp) +{ + dsp_add(asinh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *asinh_new(void) +{ + t_asinh *x = (t_asinh *)pd_new(asinh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void asinh_tilde_setup(void) +{ + asinh_class = class_new(gensym("asinh~"), + (t_newmethod)asinh_new, 0, + sizeof(t_asinh), 0, 0); + sic_setup(asinh_class, asinh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/atan.c b/cyclone/sickle/atan.c new file mode 100644 index 0000000..f541fa4 --- /dev/null +++ b/cyclone/sickle/atan.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define atanf atan +#endif + +typedef t_sic t_atan; +static t_class *atan_class; + +static t_int *atan_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = atanf(f); /* CHECKME no protection against NaNs */ + } + return (w + 4); +} + +static void atan_dsp(t_atan *x, t_signal **sp) +{ + dsp_add(atan_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *atan_new(void) +{ + t_atan *x = (t_atan *)pd_new(atan_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void atan_tilde_setup(void) +{ + atan_class = class_new(gensym("atan~"), + (t_newmethod)atan_new, 0, + sizeof(t_atan), 0, 0); + sic_setup(atan_class, atan_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/atan2.c b/cyclone/sickle/atan2.c new file mode 100644 index 0000000..171fc17 --- /dev/null +++ b/cyclone/sickle/atan2.c @@ -0,0 +1,53 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define atan2f atan2 +#endif + +typedef t_sic t_atan2; +static t_class *atan2_class; + +static t_int *atan2_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + float f1 = *in1++; + float f2 = *in2++; + /* CHECKED arg order, range (radians) */ + *out++ = atan2f(f1, f2); + } + return (w + 5); +} + +static void atan2_dsp(t_atan2 *x, t_signal **sp) +{ + dsp_add(atan2_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *atan2_new(t_floatarg f) +{ + t_atan2 *x = (t_atan2 *)pd_new(atan2_class); + sic_newinlet((t_sic *)x, f); /* CHECKED x-value argument */ + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void atan2_tilde_setup(void) +{ + atan2_class = class_new(gensym("atan2~"), + (t_newmethod)atan2_new, 0, + sizeof(t_atan2), 0, A_DEFFLOAT, 0); + sic_setup(atan2_class, atan2_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/atanh.c b/cyclone/sickle/atanh.c new file mode 100644 index 0000000..464f955 --- /dev/null +++ b/cyclone/sickle/atanh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* LATER ask about osx */ +#if defined(NT) || defined(MACOSX) +#define atanhf(x) (log((1 + x) / (1 - x)) * 0.5) +#endif + +typedef t_sic t_atanh; +static t_class *atanh_class; + +static t_int *atanh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = atanhf(f); /* CHECKME no protection against NaNs */ + } + return (w + 4); +} + +static void atanh_dsp(t_atanh *x, t_signal **sp) +{ + dsp_add(atanh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *atanh_new(void) +{ + t_atanh *x = (t_atanh *)pd_new(atanh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void atanh_tilde_setup(void) +{ + atanh_class = class_new(gensym("atanh~"), + (t_newmethod)atanh_new, 0, + sizeof(t_atanh), 0, 0); + sic_setup(atanh_class, atanh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/average.c b/cyclone/sickle/average.c new file mode 100644 index 0000000..ea330c1 --- /dev/null +++ b/cyclone/sickle/average.c @@ -0,0 +1,194 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKME no reset after changing of a window size? */ +/* CHECKME overlap */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sqrtf sqrt +#endif + +#define AVERAGE_DEFNPOINTS 100 /* CHECKME */ +#define AVERAGE_DEFMODE AVERAGE_BIPOLAR +enum { AVERAGE_BIPOLAR, AVERAGE_ABSOLUTE, AVERAGE_RMS }; + +typedef struct _average +{ + t_sic x_sic; + int x_mode; + float (*x_sumfn)(t_float*, int, float); + int x_phase; + int x_npoints; + float x_result; + float x_accum; + t_clock *x_clock; +} t_average; + +static t_class *average_class; + +static void average_tick(t_average *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_result); +} + +static float average_bipolarsum(t_float *in, int nxfer, float accum) +{ + while (nxfer--) + accum += *in++; + return (accum); +} + +static float average_absolutesum(t_float *in, int nxfer, float accum) +{ + while (nxfer--) + { + float f = *in++; + accum += (f >= 0 ? f : -f); + } + return (accum); +} + +static float average_rmssum(t_float *in, int nxfer, float accum) +{ + while (nxfer--) + { + float f = *in++; + accum += f * f; + } + return (accum); +} + +static void average_setmode(t_average *x, int mode) +{ + if (mode == AVERAGE_BIPOLAR) + x->x_sumfn = average_bipolarsum; + else if (mode == AVERAGE_ABSOLUTE) + x->x_sumfn = average_absolutesum; + else if (mode == AVERAGE_RMS) + x->x_sumfn = average_rmssum; + else + { + bug("average_setmode"); + return; + } + x->x_mode = mode; + x->x_phase = x->x_npoints; + x->x_accum = 0; +} + +static void average_float(t_average *x, t_float f) +{ + int i = (int)f; /* CHECKME noninteger */ + if (i > 0) /* CHECKME */ + { + x->x_npoints = i; + x->x_phase = x->x_npoints; + x->x_accum = 0; + } +} + +static void average_bipolar(t_average *x) +{ + average_setmode(x, AVERAGE_BIPOLAR); +} + +static void average_absolute(t_average *x) +{ + average_setmode(x, AVERAGE_ABSOLUTE); +} + +static void average_rms(t_average *x) +{ + average_setmode(x, AVERAGE_RMS); +} + +static t_int *average_perform(t_int *w) +{ + t_average *x = (t_average *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + float (*sumfn)(t_float*, int, float) = x->x_sumfn; + int phase = x->x_phase; + if (phase <= nblock) + { + float accum = (*sumfn)(in, phase, x->x_accum); + nblock -= phase; + if (x->x_mode == AVERAGE_RMS) + /* CHECKME scaling and FIXME */ + x->x_result = sqrtf(accum / x->x_npoints); + else + x->x_result = accum / x->x_npoints; + clock_delay(x->x_clock, 0); + x->x_accum = 0; + if (nblock < x->x_npoints) + x->x_phase = x->x_npoints - nblock; + else + { + x->x_phase = x->x_npoints; + return (w + 4); + } + } + else x->x_phase -= nblock; + x->x_accum = (*sumfn)(in, nblock, x->x_accum); + return (w + 4); +} + +static void average_dsp(t_average *x, t_signal **sp) +{ + dsp_add(average_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void average_free(t_average *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *average_new(t_symbol *s, t_floatarg f) +{ + t_average *x = (t_average *)pd_new(average_class); + int i = (int)f; /* CHECKME noninteger */ + int mode; + /* CHECKED it looks like memory is allocated for the entire window, + in tune with the refman's note about ``maximum averaging interval'' -- + needed for dynamic control over window size, or what? LATER rethink */ + x->x_npoints = (i > 0 ? /* CHECKME */ + i : AVERAGE_DEFNPOINTS); + if (s == gensym("bipolar")) + mode = AVERAGE_BIPOLAR; + else if (s == gensym("absolute")) + mode = AVERAGE_ABSOLUTE; + else if (s == gensym("rms")) + mode = AVERAGE_RMS; + else + { + mode = AVERAGE_DEFMODE; + /* CHECKME a warning if (s && s != &s_) */ + } + average_setmode(x, mode); + /* CHECKME if not x->x_phase = 0 */ + outlet_new((t_object *)x, &s_float); + x->x_clock = clock_new(x, (t_method)average_tick); + return (x); +} + +void average_tilde_setup(void) +{ + average_class = class_new(gensym("average~"), + (t_newmethod)average_new, + (t_method)average_free, + sizeof(t_average), 0, + A_DEFFLOAT, A_DEFSYM, 0); + sic_setup(average_class, average_dsp, average_float); + class_addmethod(average_class, (t_method)average_bipolar, + gensym("bipolar"), 0); + class_addmethod(average_class, (t_method)average_absolute, + gensym("absolute"), 0); + class_addmethod(average_class, (t_method)average_rms, + gensym("rms"), 0); +} diff --git a/cyclone/sickle/avg.c b/cyclone/sickle/avg.c new file mode 100644 index 0000000..2ad214a --- /dev/null +++ b/cyclone/sickle/avg.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _avg +{ + t_sic x_sic; + float x_count; + float x_accum; +} t_avg; + +static t_class *avg_class; + +static void avg_bang(t_avg *x) +{ + outlet_float(((t_object *)x)->ob_outlet, + (x->x_count ? x->x_accum / x->x_count : 0)); + x->x_count = 0; + x->x_accum = 0; +} + +static t_int *avg_perform(t_int *w) +{ + t_avg *x = (t_avg *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + float accum = 0; + x->x_count += nblock; /* LATER consider blockcount++ */ + while (nblock--) + { + float f = *in++; + accum += (f >= 0 ? f : -f); + } + x->x_accum += accum; + return (w + 4); +} + +static void avg_dsp(t_avg *x, t_signal **sp) +{ + dsp_add(avg_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void *avg_new(void) +{ + t_avg *x = (t_avg *)pd_new(avg_class); + outlet_new((t_object *)x, &s_float); + x->x_count = 0; + x->x_accum = 0; + return (x); +} + +void avg_tilde_setup(void) +{ + avg_class = class_new(gensym("avg~"), + (t_newmethod)avg_new, 0, + sizeof(t_avg), 0, 0); + sic_setup(avg_class, avg_dsp, SIC_FLOATTOSIGNAL); + class_addbang(avg_class, avg_bang); +} diff --git a/cyclone/sickle/bitand.c b/cyclone/sickle/bitand.c new file mode 100644 index 0000000..a7cfeb7 --- /dev/null +++ b/cyclone/sickle/bitand.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME find a way of setting a 32-bit mask in an argument */ + +#include "m_pd.h" +#include "unstable/forky.h" +#include "sickle/sic.h" + +typedef struct _bitand +{ + t_sic x_sic; + t_glist *x_glist; + t_int x_mask; /* set by a 'bits' message or a creation argument */ + int x_mode; + int x_convert1; +} t_bitand; + +static t_class *bitand_class; + +static t_int *bitand_perform(t_int *w) +{ + t_bitand *x = (t_bitand *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + t_int mask = x->x_mask; + switch (x->x_mode) + { + /* LATER think about performance */ + case 0: + /* CHECKED */ + while (nblock--) + { + t_int i = ((*(t_int *)(t_float *)in1++) & + (*(t_int *)(t_float *)in2++)); + *out++ = *(t_float *)&i; + } + break; + case 1: + /* CHECKED */ + while (nblock--) + { + t_int i = (((t_int)*in1++) & + ((t_int)*in2++)); + *out++ = (t_float)i; + } + break; + case 2: + /* CHECKED */ + while (nblock--) + { + t_int i = (*(t_int *)(t_float *)in1++) & ((t_int)*in2++); + *out++ = *(t_float *)&i; + } + break; + case 3: + /* CHECKED */ + while (nblock--) + { + t_int i = ((t_int)*in1++) & (*(t_int *)(t_float *)in2++); + *out++ = (t_float)i; + } + break; + } + return (w + 6); +} + +static t_int *bitand_perform_noin2(t_int *w) +{ + t_bitand *x = (t_bitand *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_int mask = x->x_mask; + /* LATER think about performance */ + if (x->x_convert1) while (nblock--) + { + /* CHECKED */ + t_int i = ((t_int)*in++) & mask; + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKED */ + t_int i = (*(t_int *)(t_float *)in++) & mask; + *out++ = *(t_float *)&i; + } + return (w + 5); +} + +static void bitand_dsp(t_bitand *x, t_signal **sp) +{ + if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0)) + /* use the mask set by a second inlet's signal or float, + CHECKED (incompatible) second inlet's int is persistent */ + dsp_add(bitand_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); + else /* use the mask set by a 'bits' message or a creation argument */ + dsp_add(bitand_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec); +} + +static void bitand_bits(t_bitand *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_mask = forky_getbitmask(ac, av); +} + +static void bitand_mode(t_bitand *x, t_floatarg f) +{ + int i = (int)f; + if (i < 0) + i = 0; /* CHECKED */ + else if (i > 3) + i = 3; /* CHECKED */ + x->x_mode = i; + x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3); +} + +static void *bitand_new(t_floatarg f1, t_floatarg f2) +{ + t_bitand *x = (t_bitand *)pd_new(bitand_class); + x->x_glist = canvas_getcurrent(); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_mask = (t_int)f1; /* FIXME (how?) */ + bitand_mode(x, f2); + return (x); +} + +void bitand_tilde_setup(void) +{ + bitand_class = class_new(gensym("bitand~"), + (t_newmethod)bitand_new, 0, + sizeof(t_bitand), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(bitand_class, bitand_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(bitand_class, (t_method)bitand_bits, + gensym("bits"), A_GIMME, 0); + class_addmethod(bitand_class, (t_method)bitand_mode, + gensym("mode"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/bitnot.c b/cyclone/sickle/bitnot.c new file mode 100644 index 0000000..c2929e8 --- /dev/null +++ b/cyclone/sickle/bitnot.c @@ -0,0 +1,66 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _bitnot +{ + t_sic x_sic; + int x_convert1; +} t_bitnot; + +static t_class *bitnot_class; + +static t_int *bitnot_perform(t_int *w) +{ + t_bitnot *x = (t_bitnot *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + /* LATER think about performance */ + if (x->x_convert1) while (nblock--) + { + /* CHECKME */ + t_int i = ~((t_int)*in++); + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKME */ + t_int i = ~(*(t_int *)(t_float *)in++); + *out++ = *(t_float *)&i; + } + return (w + 5); +} + +static void bitnot_dsp(t_bitnot *x, t_signal **sp) +{ + dsp_add(bitnot_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void bitnot_mode(t_bitnot *x, t_floatarg f) +{ + int i = (int)f; + x->x_convert1 = (i > 0); /* CHECKME */ +} + +static void *bitnot_new(t_floatarg f) +{ + t_bitnot *x = (t_bitnot *)pd_new(bitnot_class); + outlet_new((t_object *)x, &s_signal); + bitnot_mode(x, f); + return (x); +} + +void bitnot_tilde_setup(void) +{ + bitnot_class = class_new(gensym("bitnot~"), + (t_newmethod)bitnot_new, 0, + sizeof(t_bitnot), 0, + A_DEFFLOAT, 0); + sic_setup(bitnot_class, bitnot_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(bitnot_class, (t_method)bitnot_mode, + gensym("mode"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/bitor.c b/cyclone/sickle/bitor.c new file mode 100644 index 0000000..e5c887b --- /dev/null +++ b/cyclone/sickle/bitor.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME find a way of setting a 32-bit mask in an argument */ + +#include "m_pd.h" +#include "unstable/forky.h" +#include "sickle/sic.h" + +typedef struct _bitor +{ + t_sic x_sic; + t_glist *x_glist; + t_int x_mask; /* set by a 'bits' message or a creation argument */ + int x_mode; + int x_convert1; +} t_bitor; + +static t_class *bitor_class; + +static t_int *bitor_perform(t_int *w) +{ + t_bitor *x = (t_bitor *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + t_int mask = x->x_mask; + switch (x->x_mode) + { + /* LATER think about performance */ + case 0: + /* CHECKED */ + while (nblock--) + { + t_int i = ((*(t_int *)(t_float *)in1++) | + (*(t_int *)(t_float *)in2++)); + *out++ = *(t_float *)&i; + } + break; + case 1: + /* CHECKED */ + while (nblock--) + { + t_int i = (((t_int)*in1++) | + ((t_int)*in2++)); + *out++ = (t_float)i; + } + break; + case 2: + /* CHECKED */ + while (nblock--) + { + t_int i = (*(t_int *)(t_float *)in1++) | ((t_int)*in2++); + *out++ = *(t_float *)&i; + } + break; + case 3: + /* CHECKED */ + while (nblock--) + { + t_int i = ((t_int)*in1++) | (*(t_int *)(t_float *)in2++); + *out++ = (t_float)i; + } + break; + } + return (w + 6); +} + +static t_int *bitor_perform_noin2(t_int *w) +{ + t_bitor *x = (t_bitor *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_int mask = x->x_mask; + /* LATER think about performance */ + if (x->x_convert1) while (nblock--) + { + /* CHECKED */ + t_int i = ((t_int)*in++) | mask; + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKED */ + t_int i = (*(t_int *)(t_float *)in++) | mask; + *out++ = *(t_float *)&i; + } + return (w + 5); +} + +static void bitor_dsp(t_bitor *x, t_signal **sp) +{ + if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0)) + /* use the mask set by a second inlet's signal or float, + CHECKED (incompatible) second inlet's int is persistent */ + dsp_add(bitor_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); + else /* use the mask set by a 'bits' message or a creation argument */ + dsp_add(bitor_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec); +} + +static void bitor_bits(t_bitor *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_mask = forky_getbitmask(ac, av); +} + +static void bitor_mode(t_bitor *x, t_floatarg f) +{ + int i = (int)f; + if (i < 0) + i = 0; /* CHECKED */ + else if (i > 3) + i = 3; /* CHECKED */ + x->x_mode = i; + x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3); +} + +static void *bitor_new(t_floatarg f1, t_floatarg f2) +{ + t_bitor *x = (t_bitor *)pd_new(bitor_class); + x->x_glist = canvas_getcurrent(); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_mask = (t_int)f1; /* FIXME (how?) */ + bitor_mode(x, f2); + return (x); +} + +void bitor_tilde_setup(void) +{ + bitor_class = class_new(gensym("bitor~"), + (t_newmethod)bitor_new, 0, + sizeof(t_bitor), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(bitor_class, bitor_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(bitor_class, (t_method)bitor_bits, + gensym("bits"), A_GIMME, 0); + class_addmethod(bitor_class, (t_method)bitor_mode, + gensym("mode"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/bitshift.c b/cyclone/sickle/bitshift.c new file mode 100644 index 0000000..db30fcd --- /dev/null +++ b/cyclone/sickle/bitshift.c @@ -0,0 +1,130 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* When bit-shifting 32-bit values, gcc (intel?) bashes the second operand + modulo 32. In msp x << 32 gives 0, x >> 32 gives a propagated sign bit + (as expected). Mimicking that is clumsy. LATER consider making the calcs + more generic (use long long values?) */ + +#include "m_pd.h" +#include "sickle/sic.h" + +//#define BITSHIFT_DEBUG + +typedef struct _bitshift +{ + t_sic x_sic; + int x_convert1; + int x_lshift; + int x_rshift; + int x_lover; +} t_bitshift; + +static t_class *bitshift_class; + +static t_int *bitshift_perform(t_int *w) +{ + t_bitshift *x = (t_bitshift *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + /* LATER think about performance */ + if (x->x_lshift) + { + unsigned int shift = x->x_lshift; + if (x->x_convert1) while (nblock--) + { + /* CHECKED */ + t_int i = ((t_int)*in++ << shift); + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKED */ + t_int i = (*(t_int *)(t_float *)in++ << shift); + *out++ = *(t_float *)&i; + } + } + else if (x->x_rshift) + { + unsigned int shift = x->x_rshift; + if (x->x_convert1) while (nblock--) + { + /* CHECKME */ + t_int i = ((t_int)*in++ >> shift); + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKME */ + t_int i = (*(t_int *)(t_float *)in++ >> shift); + *out++ = *(t_float *)&i; + } + } + else if (x->x_lover) + while (nblock--) *out++ = 0; /* CHECKED both modes */ + else + while (nblock--) *out++ = *in++; /* CHECKED both modes */ + return (w + 5); +} + +static void bitshift_dsp(t_bitshift *x, t_signal **sp) +{ + dsp_add(bitshift_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void bitshift_mode(t_bitshift *x, t_floatarg f) +{ + int i = (int)f; + x->x_convert1 = (i > 0); /* CHECKED */ +} + +static void bitshift_shift(t_bitshift *x, t_floatarg f) +{ + int i = (int)f; + int nbits = sizeof(t_int) * 8; + x->x_lshift = x->x_rshift = 0; + x->x_lover = 0; + if (i > 0) + { +#ifdef BITSHIFT_DEBUG + post("%.8x << %d == %.8x, %.8x << %d == %.8x", + 1, i, 1 << i, -1, i, -1 << i); +#endif + if (i < nbits) + x->x_lshift = i; + else + x->x_lover = 1; + } + else if (i < 0) + { +#ifdef BITSHIFT_DEBUG + post("%.8x >> %d == %.8x, %.8x >> %d == %.8x", + 0x7fffffff, -i, 0x7fffffff >> -i, -1, -i, -1 >> -i); +#endif + x->x_rshift = (i <= -nbits ? nbits - 1 : -i); + } +} + +static void *bitshift_new(t_floatarg f1, t_floatarg f2) +{ + t_bitshift *x = (t_bitshift *)pd_new(bitshift_class); + outlet_new((t_object *)x, &s_signal); + bitshift_shift(x, f1); + bitshift_mode(x, f2); + return (x); +} + +void bitshift_tilde_setup(void) +{ + bitshift_class = class_new(gensym("bitshift~"), + (t_newmethod)bitshift_new, 0, + sizeof(t_bitshift), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(bitshift_class, bitshift_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(bitshift_class, (t_method)bitshift_mode, + gensym("mode"), A_FLOAT, 0); + class_addmethod(bitshift_class, (t_method)bitshift_shift, + gensym("shift"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/bitxor.c b/cyclone/sickle/bitxor.c new file mode 100644 index 0000000..ce54843 --- /dev/null +++ b/cyclone/sickle/bitxor.c @@ -0,0 +1,144 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME find a way of setting a 32-bit mask in an argument */ + +#include "m_pd.h" +#include "unstable/forky.h" +#include "sickle/sic.h" + +typedef struct _bitxor +{ + t_sic x_sic; + t_glist *x_glist; + t_int x_mask; /* set by a 'bits' message or a creation argument */ + int x_mode; + int x_convert1; +} t_bitxor; + +static t_class *bitxor_class; + +static t_int *bitxor_perform(t_int *w) +{ + t_bitxor *x = (t_bitxor *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + t_int mask = x->x_mask; + switch (x->x_mode) + { + /* LATER think about performance */ + case 0: + /* CHECKED */ + while (nblock--) + { + t_int i = ((*(t_int *)(t_float *)in1++) ^ + (*(t_int *)(t_float *)in2++)); + *out++ = *(t_float *)&i; + } + break; + case 1: + /* CHECKED */ + while (nblock--) + { + t_int i = (((t_int)*in1++) ^ + ((t_int)*in2++)); + *out++ = (t_float)i; + } + break; + case 2: + /* CHECKED */ + while (nblock--) + { + t_int i = (*(t_int *)(t_float *)in1++) ^ ((t_int)*in2++); + *out++ = *(t_float *)&i; + } + break; + case 3: + /* CHECKED */ + while (nblock--) + { + t_int i = ((t_int)*in1++) ^ (*(t_int *)(t_float *)in2++); + *out++ = (t_float)i; + } + break; + } + return (w + 6); +} + +static t_int *bitxor_perform_noin2(t_int *w) +{ + t_bitxor *x = (t_bitxor *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_int mask = x->x_mask; + /* LATER think about performance */ + if (x->x_convert1) while (nblock--) + { + /* CHECKED */ + t_int i = ((t_int)*in++) ^ mask; + *out++ = (t_float)i; + } + else while (nblock--) + { + /* CHECKED */ + t_int i = (*(t_int *)(t_float *)in++) ^ mask; + *out++ = *(t_float *)&i; + } + return (w + 5); +} + +static void bitxor_dsp(t_bitxor *x, t_signal **sp) +{ + if (forky_hasfeeders((t_object *)x, x->x_glist, 1, 0)) + /* use the mask set by a second inlet's signal or float, + CHECKED (incompatible) second inlet's int is persistent */ + dsp_add(bitxor_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); + else /* use the mask set by a 'bits' message or a creation argument */ + dsp_add(bitxor_perform_noin2, 4, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec); +} + +static void bitxor_bits(t_bitxor *x, t_symbol *s, int ac, t_atom *av) +{ + x->x_mask = forky_getbitmask(ac, av); +} + +static void bitxor_mode(t_bitxor *x, t_floatarg f) +{ + int i = (int)f; + if (i < 0) + i = 0; /* CHECKED */ + else if (i > 3) + i = 3; /* CHECKED */ + x->x_mode = i; + x->x_convert1 = (x->x_mode == 1 || x->x_mode == 3); +} + +static void *bitxor_new(t_floatarg f1, t_floatarg f2) +{ + t_bitxor *x = (t_bitxor *)pd_new(bitxor_class); + x->x_glist = canvas_getcurrent(); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_mask = (t_int)f1; /* FIXME (how?) */ + bitxor_mode(x, f2); + return (x); +} + +void bitxor_tilde_setup(void) +{ + bitxor_class = class_new(gensym("bitxor~"), + (t_newmethod)bitxor_new, 0, + sizeof(t_bitxor), 0, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(bitxor_class, bitxor_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(bitxor_class, (t_method)bitxor_bits, + gensym("bits"), A_GIMME, 0); + class_addmethod(bitxor_class, (t_method)bitxor_mode, + gensym("mode"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/capture.c b/cyclone/sickle/capture.c new file mode 100644 index 0000000..089c21e --- /dev/null +++ b/cyclone/sickle/capture.c @@ -0,0 +1,408 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKME list of indices */ + +#include <stdio.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "common/loud.h" +#include "hammer/file.h" +#include "sickle/sic.h" + +#define CAPTURE_DEFSIZE 4096 +#define CAPTURE_DEFPRECISION 4 +#define CAPTURE_MAXPRECISION 99 /* format array protection */ +#define CAPTURE_MAXINDICES 4096 /* FIXME */ + +typedef struct _capture +{ + t_sic x_sic; + t_glist *x_glist; + char x_mode; /* 'f' for first or 0 for last */ + int x_precision; + char x_format[8]; + char *x_indices; + int x_szindices; /* size of x_indices array */ + int x_nindices; /* number of reported indices */ + int x_nblock; + float *x_buffer; + int x_bufsize; + int x_count; + int x_head; + t_hammerfile *x_filehandle; +} t_capture; + +static t_class *capture_class; + +static void capture_clear(t_capture *x) +{ + x->x_count = 0; + x->x_head = 0; +} + +static int capture_formatfloat(t_capture *x, float f, char *buf, int col, + int maxcol) +{ + char *bp = buf; + int cnt = 0; + if (col > 0) + *bp++ = ' ', cnt++; + if (x->x_precision) + cnt += sprintf(bp, x->x_format, f); + else + cnt += sprintf(bp, "%d", (int)f); + if (col + cnt > maxcol) + buf[0] = '\n', col = cnt; + else + col += cnt; + return (col); +} + +static int capture_writefloat(t_capture *x, float f, char *buf, int col, + FILE *fp) +{ + /* CHECKME linebreaks */ + col = capture_formatfloat(x, f, buf, col, 80); + return (fputs(buf, fp) < 0 ? -1 : col); +} + +static void capture_dowrite(t_capture *x, t_symbol *fn) +{ + FILE *fp = 0; + int count = x->x_count; + char buf[MAXPDSTRING]; + canvas_makefilename(glist_getcanvas(x->x_glist), + fn->s_name, buf, MAXPDSTRING); + if (fp = fopen(buf, "w")) /* LATER ask if overwriting, CHECKME */ + { + int col = 0; + if (x->x_mode == 'f' || count < x->x_bufsize) + { + float *bp = x->x_buffer; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + } + else + { + float *bp = x->x_buffer + x->x_head; + count = x->x_bufsize - x->x_head; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + bp = x->x_buffer; + count = x->x_head; + while (count--) + if ((col = capture_writefloat(x, *bp++, buf, col, fp)) < 0) + goto fail; + } + if (col) fputc('\n', fp); + fclose(fp); + return; + } +fail: + if (fp) fclose(fp); + loud_syserror((t_pd *)x, 0); +} + +static void capture_writehook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + capture_dowrite((t_capture *)z, fn); +} + +static void capture_write(t_capture *x, t_symbol *s) +{ + if (s && s != &s_) + capture_dowrite(x, s); + else + hammerpanel_save(x->x_filehandle, 0, 0); +} + +static int capture_appendfloat(t_capture *x, float f, char *buf, + int col, int linebreak) +{ + /* CHECKME 80 columns */ + col = capture_formatfloat(x, f, buf, col, 80); + hammereditor_append(x->x_filehandle, buf); + if (linebreak) + { + if (col) + { + hammereditor_append(x->x_filehandle, "\n\n"); + col = 0; + } + else hammereditor_append(x->x_filehandle, "\n"); + } + return (col); +} + +/* CHECKED blank line between blocks */ +static void capture_open(t_capture *x) +{ + int count = x->x_count; + char buf[MAXPDSTRING]; + int nindices = (x->x_nindices > 0 ? x->x_nindices : x->x_nblock); + hammereditor_open(x->x_filehandle, "Signal Capture"); /* CHECKED */ + if (x->x_mode == 'f' || count < x->x_bufsize) + { + float *bp = x->x_buffer; + int col = 0, i; + for (i = 1; i <= count; i++) + col = capture_appendfloat(x, *bp++, buf, col, + ((i % nindices) == 0)); + } + else + { + float *bp = x->x_buffer + x->x_head; + int col = 0, i = x->x_bufsize; + count = x->x_bufsize - x->x_head; + while (count--) + col = capture_appendfloat(x, *bp++, buf, col, + ((--i % nindices) == 0)); + bp = x->x_buffer; + count = x->x_head; + while (count--) + col = capture_appendfloat(x, *bp++, buf, col, + ((count % nindices) == 0)); + } +} + +static void capture_wclose(t_capture *x) +{ + hammereditor_close(x->x_filehandle, 0); +} + +static void capture_click(t_capture *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + capture_open(x); +} + +static t_int *capture_perform_first(t_int *w) +{ + t_capture *x = (t_capture *)(w[1]); + int count = x->x_count; + int bufsize = x->x_bufsize; + if (count < bufsize) + { + t_float *in = (t_float *)(w[2]); + int nblock = (int)(w[3]); + float *bp = x->x_buffer + count; + char *ndxp = x->x_indices; + if (nblock > x->x_szindices) + nblock = x->x_szindices; + while (nblock--) + { + if (*ndxp++) + { + *bp++ = *in++; + if (++count == bufsize) + break; + } + else in++; + } + x->x_count = count; + } + return (w + 4); +} + +static t_int *capture_perform_allfirst(t_int *w) +{ + t_capture *x = (t_capture *)(w[1]); + int count = x->x_count; + int bufsize = x->x_bufsize; + if (count < bufsize) + { + t_float *in = (t_float *)(w[2]); + int nblock = (int)(w[3]); + float *bp = x->x_buffer + count; + while (nblock--) + { + *bp++ = *in++; + if (++count == bufsize) + break; + } + x->x_count = count; + } + return (w + 4); +} + +static t_int *capture_perform_last(t_int *w) +{ + t_capture *x = (t_capture *)(w[1]); + t_float *in = (t_float *)(w[2]); + int nblock = (int)(w[3]); + float *buffer = x->x_buffer; + int bufsize = x->x_bufsize; + int count = x->x_count; + int head = x->x_head; + char *ndxp = x->x_indices; + if (nblock > x->x_szindices) + nblock = x->x_szindices; + while (nblock--) + { + if (*ndxp++) + { + buffer[head++] = *in++; + if (head >= bufsize) + head = 0; + if (count < bufsize) + count++; + } + else in++; + } + x->x_count = count; + x->x_head = head; + return (w + 4); +} + +static t_int *capture_perform_alllast(t_int *w) +{ + t_capture *x = (t_capture *)(w[1]); + t_float *in = (t_float *)(w[2]); + int nblock = (int)(w[3]); + float *buffer = x->x_buffer; + int bufsize = x->x_bufsize; + int count = x->x_count; + int head = x->x_head; + while (nblock--) + { + buffer[head++] = *in++; + if (head >= bufsize) + head = 0; + if (count < bufsize) + count++; + } + x->x_count = count; + x->x_head = head; + return (w + 4); +} + +static void capture_dsp(t_capture *x, t_signal **sp) +{ + x->x_nblock = sp[0]->s_n; + if (x->x_indices) + dsp_add((x->x_mode == 'f' ? + capture_perform_first : capture_perform_last), + 3, x, sp[0]->s_vec, sp[0]->s_n); + else + dsp_add((x->x_mode == 'f' ? + capture_perform_allfirst : capture_perform_alllast), + 3, x, sp[0]->s_vec, sp[0]->s_n); +} + +static void capture_free(t_capture *x) +{ + hammerfile_free(x->x_filehandle); + if (x->x_indices) + freebytes(x->x_indices, x->x_szindices * sizeof(*x->x_indices)); + if (x->x_buffer) + freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer)); +} + +static void *capture_new(t_symbol *s, int ac, t_atom *av) +{ + t_capture *x = 0; + char mode = 0; + int precision = -1; + float *buffer; + int bufsize = 0; + char *indices = 0; + int szindices = 0, nindices = -1; + if (ac && av->a_type == A_SYMBOL) + { + t_symbol *s = av->a_w.w_symbol; + if (s && *s->s_name == 'f') /* CHECKME */ + mode = 'f'; + ac--; av++; + } + if (ac && av->a_type == A_FLOAT) + { + bufsize = (int)av->a_w.w_float; /* CHECKME */ + ac--; av++; + if (ac && av->a_type == A_FLOAT) + { + int i; + t_atom *ap; + precision = (int)av->a_w.w_float; /* CHECKME */ + ac--; av++; + for (i = 0, ap = av; i < ac; i++, ap++) + { + if (ap->a_type == A_FLOAT) + { + int ndx = (int)ap->a_w.w_float; + /* CHECKME noninteger, negative */ + ndx++; + if (ndx >= CAPTURE_MAXINDICES) + { + /* CHECKME complaint */ + szindices = CAPTURE_MAXINDICES; + break; + } + else if (ndx > szindices) + szindices = ndx; + } + else break; /* CHECKME */ + } + if (szindices && (indices = getbytes(szindices * sizeof(*indices)))) + { + nindices = 0; + while (i--) + { + int ndx = (int)av++->a_w.w_float; + /* CHECKME noninteger */ + if (ndx >= 0 && ndx < szindices) + indices[ndx] = 1, nindices++; + } + } + } + } + if (bufsize <= 0) /* CHECKME */ + bufsize = CAPTURE_DEFSIZE; + if (buffer = getbytes(bufsize * sizeof(*buffer))) + { + x = (t_capture *)pd_new(capture_class); + x->x_glist = canvas_getcurrent(); + x->x_mode = mode; + if (precision < 0) /* CHECKME */ + precision = CAPTURE_DEFPRECISION; + else if (precision > CAPTURE_MAXPRECISION) /* CHECKME */ + precision = CAPTURE_MAXPRECISION; + if (x->x_precision = precision) + sprintf(x->x_format, "%%.%dg", precision); + x->x_indices = indices; + x->x_szindices = szindices; + x->x_nindices = nindices; + x->x_nblock = 64; /* redundant */ + x->x_buffer = buffer; + x->x_bufsize = bufsize; + x->x_filehandle = hammerfile_new((t_pd *)x, 0, 0, capture_writehook, 0); + capture_clear(x); + } + else if (indices) + freebytes(indices, szindices * sizeof(*indices)); + return (x); +} + +void capture_tilde_setup(void) +{ + capture_class = class_new(gensym("capture~"), + (t_newmethod)capture_new, + (t_method)capture_free, + sizeof(t_capture), 0, A_GIMME, 0); + sic_setup(capture_class, capture_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(capture_class, (t_method)capture_clear, + gensym("clear"), 0); + class_addmethod(capture_class, (t_method)capture_write, + gensym("write"), A_DEFSYM, 0); + class_addmethod(capture_class, (t_method)capture_open, + gensym("open"), 0); + class_addmethod(capture_class, (t_method)capture_wclose, + gensym("wclose"), 0); + class_addmethod(capture_class, (t_method)capture_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(capture_class, 0); +} diff --git a/cyclone/sickle/cartopol.c b/cyclone/sickle/cartopol.c new file mode 100644 index 0000000..4c25797 --- /dev/null +++ b/cyclone/sickle/cartopol.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "unstable/fragile.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define atan2f atan2 +#define hypotf hypot +#endif + +typedef struct _cartopol +{ + t_sic x_sic; + t_outlet *x_out2; +} t_cartopol; + +static t_class *cartopol_class; + +static t_int *cartopol_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out1 = (t_float *)(w[4]); + t_float *out2 = (t_float *)(w[5]); + while (nblock--) + { + float rl = *in1++, im = -*in2++; /* CHECKED */ + *out1++ = hypotf(rl, im); + *out2++ = atan2f(im, rl); + } + return (w + 6); +} + +static t_int *cartopol_perform_nophase(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out1 = (t_float *)(w[4]); + while (nblock--) + { + float rl = *in1++, im = -*in2++; /* CHECKED */ + *out1++ = hypotf(rl, im); + } + return (w + 5); +} + +static void cartopol_dsp(t_cartopol *x, t_signal **sp) +{ + if (fragile_outlet_connections(x->x_out2)) + dsp_add(cartopol_perform, 5, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); + else + dsp_add(cartopol_perform_nophase, 4, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); +} + +static void *cartopol_new(void) +{ + t_cartopol *x = (t_cartopol *)pd_new(cartopol_class); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_out2 = outlet_new((t_object *)x, &s_signal); + return (x); +} + +void cartopol_tilde_setup(void) +{ + cartopol_class = class_new(gensym("cartopol~"), + (t_newmethod)cartopol_new, 0, + sizeof(t_cartopol), 0, 0); + sic_setup(cartopol_class, cartopol_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/change.c b/cyclone/sickle/change.c new file mode 100644 index 0000000..fffc43a --- /dev/null +++ b/cyclone/sickle/change.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _change +{ + t_sic x_sic; + t_float x_last; +} t_change; + +static t_class *change_class; + +static t_int *change_perform(t_int *w) +{ + t_change *x = (t_change *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float last = x->x_last; + while (nblock--) + { + t_float f = *in++; + *out++ = (f > last ? 1. : (f < last ? -1. : 0.)); + last = f; + } + x->x_last = last; + return (w + 5); +} + +static void change_dsp(t_change *x, t_signal **sp) +{ + dsp_add(change_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *change_new(void) +{ + t_change *x = (t_change *)pd_new(change_class); + outlet_new((t_object *)x, &s_signal); + x->x_last = 0; /* CHECKME startup conditions */ + return (x); +} + +void change_tilde_setup(void) +{ + change_class = class_new(gensym("change~"), + (t_newmethod)change_new, 0, + sizeof(t_change), 0, 0); + sic_setup(change_class, change_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/click.c b/cyclone/sickle/click.c new file mode 100644 index 0000000..5734cfd --- /dev/null +++ b/cyclone/sickle/click.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "common/grow.h" +#include "sickle/sic.h" + +#define CLICK_INISIZE 16 /* LATER rethink */ + +typedef struct _click +{ + t_sic x_sic; + int x_nsamples; /* as used */ + int x_bufsize; /* as allocated */ + t_float *x_buffer; + t_float x_bufini[CLICK_INISIZE]; + int x_nleft; + t_float *x_head; +} t_click; + +static t_class *click_class; + +static void click_bang(t_click *x) +{ + x->x_nleft = x->x_nsamples; + x->x_head = x->x_buffer; +} + +static void click_set(t_click *x, t_symbol *s, int ac, t_atom *av) +{ + int i, nsamples = 0; + t_atom *ap; + t_float *bp; + for (i = 0, ap = av; i < ac; i++, ap++) + { + if (ap->a_type == A_FLOAT) nsamples++; + /* CHECKED no restrictions (refman's error about 0.0-1.0 range) + CHECKED nonnumeric atoms silently ignored */ + } + if (nsamples > x->x_bufsize) + x->x_buffer = grow_nodata(&nsamples, &x->x_bufsize, x->x_buffer, + CLICK_INISIZE, x->x_bufini, + sizeof(*x->x_buffer)); + if (nsamples) + { + x->x_nsamples = nsamples; + bp = x->x_buffer; + while (nsamples--) *bp++ = av++->a_w.w_float; + } + else x->x_nsamples = 0; /* CHECKED, need to 'set 1' explicitly */ + x->x_nleft = 0; + x->x_head = x->x_buffer; +} + +static t_int *click_perform(t_int *w) +{ + t_click *x = (t_click *)(w[1]); + int nblock = (int)(w[2]); + t_float *out = (t_float *)(w[3]); + if (x->x_nleft) + { + int nleft = x->x_nleft; + t_float *head = x->x_head; + if (nleft >= nblock) + { + x->x_nleft -= nblock; + while (nblock--) *out++ = *head++; + x->x_head = head; + } + else + { + nblock -= nleft; + while (nleft--) *out++ = *head++; + while (nblock--) *out++ = 0.; + x->x_nleft = 0; + x->x_head = x->x_buffer; + } + } + else while (nblock--) *out++ = 0.; + return (w + 4); +} + +static void click_dsp(t_click *x, t_signal **sp) +{ + dsp_add(click_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void click_free(t_click *x) +{ + if (x->x_buffer != x->x_bufini) + freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer)); +} + +static void *click_new(t_symbol *s, int ac, t_atom *av) +{ + t_click *x = (t_click *)pd_new(click_class); + x->x_nsamples = 1; /* CHECKED */ + x->x_bufsize = CLICK_INISIZE; + x->x_buffer = x->x_bufini; + x->x_buffer[0] = 1.; /* CHECKED */ + x->x_nleft = 0; + x->x_head = x->x_buffer; + outlet_new((t_object *)x, &s_signal); + if (ac) click_set(x, 0, ac, av); + return (x); +} + +void click_tilde_setup(void) +{ + click_class = class_new(gensym("click~"), + (t_newmethod)click_new, + (t_method)click_free, + sizeof(t_click), 0, A_GIMME, 0); + sic_setup(click_class, click_dsp, SIC_NOMAINSIGNALIN); + class_addbang(click_class, click_bang); + class_addmethod(click_class, (t_method)click_set, + gensym("set"), A_GIMME, 0); +} diff --git a/cyclone/sickle/comb.c b/cyclone/sickle/comb.c new file mode 100644 index 0000000..8d4c8b3 --- /dev/null +++ b/cyclone/sickle/comb.c @@ -0,0 +1,162 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _comb +{ + t_sic x_sic; + float x_sr; + float x_ksr; + t_float *x_buf; + int x_bufsize; /* as allocated */ + int x_maxsize; /* as used */ + float x_maxdelay; /* same in ms */ + int x_phase; /* writing head */ +} t_comb; + +static t_class *comb_class; + +/* maximum delay defaults to 50 ms (cycling has 10 ms here) */ +#define COMB_DEFMAXDELAY 50.0 + +/* LATER choose the best way. From msp help patch: + no clipping is done on a, b, or c coefficient input */ +#define COMB_MAXFEEDBACK 0.999 + +static void comb_clear(t_comb *x) +{ + memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf)); + x->x_phase = 0; +} + +static void comb_resize(t_comb *x, int newsize) +{ + if (newsize > 0 && newsize != x->x_maxsize) + { + if (newsize > x->x_bufsize) + { + x->x_buf = resizebytes(x->x_buf, + x->x_bufsize * sizeof(*x->x_buf), + newsize * sizeof(*x->x_buf)); + /* LATER test for failure */ + x->x_bufsize = newsize; + } + x->x_maxsize = newsize; + } + comb_clear(x); +} + +static t_int *comb_perform(t_int *w) +{ + t_comb *x = (t_comb *)(w[1]); + int nblock = (int)(w[2]); + t_float *xin = (t_float *)(w[3]); + t_float *din = (t_float *)(w[4]); + t_float *ain = (t_float *)(w[5]); + t_float *bin = (t_float *)(w[6]); + t_float *cin = (t_float *)(w[7]); + t_float *out = (t_float *)(w[8]); + t_float *buf = x->x_buf; + int maxsize = x->x_maxsize; + int guardpoint = maxsize - 1; + float ksr = x->x_ksr; + int wph = x->x_phase; + while (nblock--) + { /* TDFII scheme is used. Do not forget, that any signal value + read after writing to out has to be saved beforehand. */ + float xn = *xin++; + float delsize = ksr * *din++; + float bgain = *bin++; + float cgain = *cin++; + float yn = *ain++ * xn; + float rph; /* reading head */ + if (cgain < -COMB_MAXFEEDBACK) cgain = -COMB_MAXFEEDBACK; + else if (cgain > COMB_MAXFEEDBACK) cgain = COMB_MAXFEEDBACK; + if (delsize > 1.0) + { + int ndx; + float val; + rph = wph - (delsize > guardpoint ? guardpoint : delsize); + if (rph < 0) rph += guardpoint; + ndx = (int)rph; + val = buf[ndx]; + /* ``a cheezy linear interpolation'' ala msp, + (vd~ uses 4-point interpolation...) */ + yn += val + (buf[ndx+1] - val) * (rph - ndx); + } + *out++ = yn; + if (wph == guardpoint) + { + buf[wph] = *buf = bgain * xn + cgain * yn; + wph = 1; + } + else buf[wph++] = bgain * xn + cgain * yn; + } + x->x_phase = wph; + return (w + 9); +} + +static void comb_dsp(t_comb *x, t_signal **sp) +{ + float sr = sp[0]->s_sr; + if (sr != x->x_sr) + { + x->x_sr = sr; + x->x_ksr = sr * 0.001; + comb_resize(x, x->x_ksr * x->x_maxdelay); + } + else comb_clear(x); + dsp_add(comb_perform, 8, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, + sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec); +} + +static void *comb_new(t_floatarg f1, t_floatarg f2, + t_floatarg f3, t_floatarg f4, t_floatarg f5) +{ + t_comb *x; + float maxdelay = (f1 > 0 ? f1 : COMB_DEFMAXDELAY); + float sr = sys_getsr(); + float ksr = sr * 0.001; + int bufsize = ksr * maxdelay; + t_float *buf = (t_float *)getbytes(bufsize * sizeof(*buf)); + if (!buf) + return (0); + x = (t_comb *)pd_new(comb_class); + x->x_maxdelay = maxdelay; + x->x_sr = sr; + x->x_ksr = ksr; + x->x_bufsize = x->x_maxsize = bufsize; + x->x_buf = buf; + if (f2 < 0) f2 = 0; + if (f5 < -COMB_MAXFEEDBACK) f5 = -COMB_MAXFEEDBACK; + else if (f5 > COMB_MAXFEEDBACK) f5 = COMB_MAXFEEDBACK; + sic_newinlet((t_sic *)x, f2); + sic_newinlet((t_sic *)x, f3); + sic_newinlet((t_sic *)x, f4); + sic_newinlet((t_sic *)x, f5); + outlet_new((t_object *)x, &s_signal); + comb_clear(x); + return (x); +} + +static void comb_free(t_comb *x) +{ + if (x->x_buf) freebytes(x->x_buf, x->x_bufsize * sizeof(*x->x_buf)); +} + +void comb_tilde_setup(void) +{ + comb_class = class_new(gensym("comb~"), + (t_newmethod)comb_new, + (t_method)comb_free, + sizeof(t_comb), 0, + A_DEFFLOAT, A_DEFFLOAT, + A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(comb_class, comb_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(comb_class, (t_method)comb_clear, gensym("clear"), 0); +} diff --git a/cyclone/sickle/cosh.c b/cyclone/sickle/cosh.c new file mode 100644 index 0000000..ae5f8cb --- /dev/null +++ b/cyclone/sickle/cosh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define coshf cosh +#endif + +typedef t_sic t_cosh; +static t_class *cosh_class; + +static t_int *cosh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = coshf(f); /* CHECKME no protection against overflow */ + } + return (w + 4); +} + +static void cosh_dsp(t_cosh *x, t_signal **sp) +{ + dsp_add(cosh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *cosh_new(void) +{ + t_cosh *x = (t_cosh *)pd_new(cosh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void cosh_tilde_setup(void) +{ + cosh_class = class_new(gensym("cosh~"), + (t_newmethod)cosh_new, 0, + sizeof(t_cosh), 0, 0); + sic_setup(cosh_class, cosh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/cosx.c b/cyclone/sickle/cosx.c new file mode 100644 index 0000000..b368559 --- /dev/null +++ b/cyclone/sickle/cosx.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* by definition, this is just an interface to the -lm call + (do not use costable) */ + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define cosf cos +#endif + +typedef t_sic t_cosx; +static t_class *cosx_class; + +static t_int *cosx_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = cosf(f); + } + return (w + 4); +} + +static void cosx_dsp(t_cosx *x, t_signal **sp) +{ + dsp_add(cosx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *cosx_new(void) +{ + t_cosx *x = (t_cosx *)pd_new(cosx_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void cosx_tilde_setup(void) +{ + cosx_class = class_new(gensym("cosx~"), + (t_newmethod)cosx_new, 0, + sizeof(t_cosx), 0, 0); + sic_setup(cosx_class, cosx_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/count.c b/cyclone/sickle/count.c new file mode 100644 index 0000000..b2ed2cd --- /dev/null +++ b/cyclone/sickle/count.c @@ -0,0 +1,145 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _count +{ + t_sic x_sic; + int x_min; + int x_max; + int x_limit; + int x_on; + int x_autoreset; + int x_count; /* MAYBE use 64 bits (if 13.5 hours is not enough...) */ +} t_count; + +static t_class *count_class; + +static void count_min(t_count *x, t_floatarg f) +{ + x->x_min = (int)f; +} + +static void count_max(t_count *x, t_floatarg f) +{ + x->x_max = (int)f; + /* MAYBE use 64 bits */ + x->x_limit = (x->x_max == 0 ? 0x7fffffff + : x->x_max - 1); /* CHECKED */ +} + +static void count_autoreset(t_count *x, t_floatarg f) +{ + x->x_autoreset = (f != 0); +} + +static void count_bang(t_count *x) +{ + x->x_count = x->x_min; + x->x_on = 1; +} + +static void count_float(t_count *x, t_floatarg f) +{ + x->x_count = x->x_min = (int)f; + x->x_on = 1; +} + +static void count_list(t_count *x, t_symbol *s, int ac, t_atom *av) +{ + int i; + if (ac > 4) ac = 4; + for (i = 0; i < ac; i++) + if (av[i].a_type != A_FLOAT) break; + switch (i) + { + case 4: + count_autoreset(x, av[3].a_w.w_float); + case 3: + x->x_on = (av[2].a_w.w_float != 0); + case 2: + count_max(x, av[1].a_w.w_float); + case 1: + count_min(x, av[0].a_w.w_float); + default: + x->x_count = x->x_min; + } +} + +static void count_set(t_count *x, t_symbol s, int ac, t_atom *av) +{ + if (av[0].a_type == A_FLOAT) count_min(x, av[0].a_w.w_float); + if (av[1].a_type == A_FLOAT) count_max(x, av[1].a_w.w_float); +} + +static void count_stop(t_count *x) +{ + x->x_count = x->x_min; + x->x_on = 0; +} + +static t_int *count_perform(t_int *w) +{ + t_count *x = (t_count *)(w[1]); + int nblock = (int)(w[2]); + t_float *out = (t_float *)(w[3]); + int count = x->x_count; + int limit = x->x_limit; + if (x->x_on) + { + while (nblock--) + { + if (count > limit) count = x->x_min; + *out++ = (t_float)count++; + } + } + else + while (nblock--) *out++ = count; + x->x_count = count; + return (w + 4); +} + +static void count_dsp(t_count *x, t_signal **sp) +{ + if (x->x_autoreset) count_bang(x); + dsp_add(count_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void *count_new(t_floatarg minval, t_floatarg maxval, + t_floatarg onflag, t_floatarg autoflag) +{ + t_count *x = (t_count *)pd_new(count_class); + count_min(x, minval); + count_max(x, maxval); + x->x_on = (onflag != 0); + count_autoreset(x, autoflag); + x->x_count = x->x_min; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void count_tilde_setup(void) +{ + count_class = class_new(gensym("count~"), + (t_newmethod)count_new, 0, + sizeof(t_count), 0, + A_DEFFLOAT, A_DEFFLOAT, + A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(count_class, count_dsp, SIC_NOMAINSIGNALIN); + class_addbang(count_class, count_bang); + class_addfloat(count_class, count_float); + class_addlist(count_class, count_list); + class_addmethod(count_class, (t_method)count_max, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(count_class, (t_method)count_autoreset, + gensym("autoreset"), A_FLOAT, 0); + class_addmethod(count_class, (t_method)count_min, + gensym("min"), A_FLOAT, 0); + class_addmethod(count_class, (t_method)count_set, + gensym("set"), A_GIMME, 0); + class_addmethod(count_class, (t_method)count_stop, gensym("stop"), 0); +} diff --git a/cyclone/sickle/cycle.c b/cyclone/sickle/cycle.c new file mode 100644 index 0000000..01500ba --- /dev/null +++ b/cyclone/sickle/cycle.c @@ -0,0 +1,173 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "shared.h" +#include "common/loud.h" +#include "common/vefl.h" +#include "sickle/sic.h" + +#define CYCLE_TABSIZE 512 + +typedef struct _cycle +{ + t_sic x_sic; + double x_phase; + double x_conv; + t_symbol *x_name; + int x_offset; + t_float *x_table; + t_float *x_costable; + t_float x_usertable[CYCLE_TABSIZE + 1]; +} t_cycle; + +static t_class *cycle_class; + +static void cycle_gettable(t_cycle *x) +{ + x->x_table = 0; + if (x->x_name) + { + int tabsize = 0; + t_float *table = vefl_get(x->x_name, &tabsize, 1, (t_pd *)x); + /* CHECKED buffer is copied */ + if (table) + { + int indx = x->x_offset + CYCLE_TABSIZE; + t_float *ptr = x->x_usertable + CYCLE_TABSIZE; + if (indx == tabsize) + { + *ptr-- = *table; + indx--; + } + if (indx < tabsize) + { + table += indx; + indx -= x->x_offset; + while (indx--) *ptr-- = *table--; + x->x_table = x->x_usertable; + } + /* CHECKED else no complaint */ + } + } + else x->x_table = x->x_costable; + if (!x->x_table) + { + /* CHECKED (incompatible) cycle~ is disabled -- garbage is output */ + x->x_table = x->x_usertable; + memset(x->x_table, 0, (CYCLE_TABSIZE + 1) * sizeof(*x->x_table)); + } +} + +static void cycle_set(t_cycle *x, t_symbol *s, t_floatarg f) +{ + if (s && s != &s_) + { + x->x_name = s; + if ((x->x_offset = (int)f) < 0) + x->x_offset = 0; + } + else x->x_name = 0; + cycle_gettable(x); +} + +static t_int *cycle_perform(t_int *w) +{ + t_cycle *x = (t_cycle *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + t_float *tab = x->x_table; + t_float *addr, f1, f2, frac; + double dphase = x->x_phase + SHARED_UNITBIT32; + double conv = x->x_conv; + int32 normhipart; + t_shared_wrappy wrappy; + + wrappy.w_d = SHARED_UNITBIT32; + normhipart = wrappy.w_i[SHARED_HIOFFSET]; + + wrappy.w_d = dphase + CYCLE_TABSIZE * *in2++; /* CHECKED */ + dphase += *in1++ * conv; + addr = tab + (wrappy.w_i[SHARED_HIOFFSET] & (CYCLE_TABSIZE-1)); + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + frac = wrappy.w_d - SHARED_UNITBIT32; + + while (--nblock) + { + wrappy.w_d = dphase + CYCLE_TABSIZE * *in2++; /* CHECKED */ + dphase += *in1++ * conv; + f1 = addr[0]; + f2 = addr[1]; + addr = tab + (wrappy.w_i[SHARED_HIOFFSET] & (CYCLE_TABSIZE-1)); + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + *out++ = f1 + frac * (f2 - f1); + frac = wrappy.w_d - SHARED_UNITBIT32; + } + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); + + wrappy.w_d = SHARED_UNITBIT32 * CYCLE_TABSIZE; + normhipart = wrappy.w_i[SHARED_HIOFFSET]; + wrappy.w_d = dphase + (SHARED_UNITBIT32 * CYCLE_TABSIZE - SHARED_UNITBIT32); + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + x->x_phase = wrappy.w_d - (SHARED_UNITBIT32 * CYCLE_TABSIZE); + return (w + 6); +} + +static void cycle_dsp(t_cycle *x, t_signal **sp) +{ + cycle_gettable(x); + x->x_conv = CYCLE_TABSIZE / sp[0]->s_sr; + dsp_add(cycle_perform, 5, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *cycle_new(t_symbol *s, int ac, t_atom *av) +{ + t_cycle *x = (t_cycle *)pd_new(cycle_class); + int i = (ac && av->a_type == A_FLOAT ? 1 : 0); + int tabsize = CYCLE_TABSIZE; + x->x_costable = sic_makecostable(&tabsize); + if (tabsize != CYCLE_TABSIZE) + { + bug("cycle_new"); + pd_free((t_pd *)x); + return (0); + } + if (ac && av->a_type == A_FLOAT) + { + sic_inlet((t_sic *)x, 0, 0, 0, ac, av); + ac--, av++; + } + sic_newinlet((t_sic *)x, 0); + outlet_new((t_object *)x, &s_signal); + x->x_offset = 0; + if (ac && av->a_type == A_SYMBOL) + { + x->x_name = av->a_w.w_symbol; + ac--, av++; + if (ac && av->a_type == A_FLOAT) + if ((x->x_offset = (int)av->a_w.w_float) < 0) + x->x_offset = 0; + } + else x->x_name = 0; + x->x_table = 0; + x->x_phase = 0.; + x->x_conv = 0.; + return (x); +} + +void cycle_tilde_setup(void) +{ + cycle_class = class_new(gensym("cycle~"), + (t_newmethod)cycle_new, 0, + sizeof(t_cycle), 0, A_GIMME, 0); + sic_setup(cycle_class, cycle_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(cycle_class, (t_method)cycle_set, + gensym("set"), A_DEFSYMBOL, A_DEFFLOAT, 0); +} diff --git a/cyclone/sickle/delay.c b/cyclone/sickle/delay.c new file mode 100644 index 0000000..b0ddd9d --- /dev/null +++ b/cyclone/sickle/delay.c @@ -0,0 +1,101 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _delay +{ + t_sic x_sic; + t_float *x_buf; + t_float *x_bufend; + t_float *x_whead; + int x_maxsize; + int x_delsize; +} t_delay; + +static t_class *delay_class; + +#define DELAY_DEFMAXSIZE 512 + +static void delay_ft1(t_delay *x, t_floatarg f) +{ + x->x_delsize = (f > 0 ? (int)f : 0); + if (x->x_delsize > x->x_maxsize) + x->x_delsize = x->x_maxsize; /* CHECKED */ + /* CHECKED: all buffered values should be available */ +} + +static t_int *delay_perform(t_int *w) +{ + t_delay *x = (t_delay *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float *buf = x->x_buf; + t_float *ep = x->x_bufend; + t_float *wp = x->x_whead; + if (x->x_delsize) + { + t_float *rp = wp - x->x_delsize; + if (rp < buf) rp += x->x_maxsize; + while (nblock--) + { + float f = *in++; + *out++ = *rp; + if (rp++ == ep) rp = buf; + *wp = f; + if (wp++ == ep) wp = buf; + } + } + else while (nblock--) + { + *out++ = *wp = *in++; + if (wp++ == ep) wp = buf; + } + x->x_whead = wp; + return (w + 5); +} + +static void delay_dsp(t_delay *x, t_signal **sp) +{ + memset(x->x_buf, 0, x->x_maxsize * sizeof(*x->x_buf)); /* CHECKED */ + x->x_whead = x->x_buf; + dsp_add(delay_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *delay_new(t_floatarg f1, t_floatarg f2) +{ + t_delay *x; + int maxsize = (f1 > 0 ? (int)f1 : DELAY_DEFMAXSIZE); + t_float *buf = (t_float *)getbytes(maxsize * sizeof(*buf)); + if (!buf) + return (0); + x = (t_delay *)pd_new(delay_class); + x->x_maxsize = maxsize; + x->x_buf = x->x_whead = buf; + x->x_bufend = buf + maxsize - 1; + x->x_delsize = (f2 > 0 ? (int)f2 : 0); + if (x->x_delsize > maxsize) + x->x_delsize = maxsize; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +static void delay_free(t_delay *x) +{ + if (x->x_buf) freebytes(x->x_buf, x->x_maxsize * sizeof(*x->x_buf)); +} + +void delay_tilde_setup(void) +{ + delay_class = class_new(gensym("delay~"), + (t_newmethod)delay_new, (t_method)delay_free, + sizeof(t_delay), 0, A_DEFFLOAT, A_DEFFLOAT, 0); + sic_setup(delay_class, delay_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(delay_class, (t_method)delay_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/delta.c b/cyclone/sickle/delta.c new file mode 100644 index 0000000..145d6b7 --- /dev/null +++ b/cyclone/sickle/delta.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _delta +{ + t_sic x_sic; + t_float x_last; +} t_delta; + +static t_class *delta_class; + +static t_int *delta_perform(t_int *w) +{ + t_delta *x = (t_delta *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float last = x->x_last; + while (nblock--) + { + t_float f = *in++; + *out++ = f - last; + last = f; + } + x->x_last = last; + return (w + 5); +} + +static void delta_dsp(t_delta *x, t_signal **sp) +{ + dsp_add(delta_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *delta_new(void) +{ + t_delta *x = (t_delta *)pd_new(delta_class); + outlet_new((t_object *)x, &s_signal); + x->x_last = 0; + return (x); +} + +void delta_tilde_setup(void) +{ + delta_class = class_new(gensym("delta~"), + (t_newmethod)delta_new, 0, + sizeof(t_delta), 0, 0); + sic_setup(delta_class, delta_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/deltaclip.c b/cyclone/sickle/deltaclip.c new file mode 100644 index 0000000..89c9321 --- /dev/null +++ b/cyclone/sickle/deltaclip.c @@ -0,0 +1,67 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" + +#define DELTACLIP_DEFLO 0. +#define DELTACLIP_DEFHI 0. + +typedef struct _deltaclip +{ + t_sic x_sic; + t_float x_last; +} t_deltaclip; + +static t_class *deltaclip_class; + +static t_int *deltaclip_perform(t_int *w) +{ + t_deltaclip *x = (t_deltaclip *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *in3 = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + t_float last = x->x_last; + while (nblock--) + { + float f = *in1++; + float delta = f - last; + float lo = *in2++; + float hi = *in3++; + if (delta < lo) + f = last + lo; + else if (delta > hi) + f = last + hi; + *out++ = last = f; + } + x->x_last = last; + return (w + 7); +} + +static void deltaclip_dsp(t_deltaclip *x, t_signal **sp) +{ + dsp_add(deltaclip_perform, 6, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void *deltaclip_new(t_symbol *s, int ac, t_atom *av) +{ + t_deltaclip *x = (t_deltaclip *)pd_new(deltaclip_class); + sic_inlet((t_sic *)x, 1, DELTACLIP_DEFLO, 0, ac, av); + sic_inlet((t_sic *)x, 2, DELTACLIP_DEFHI, 1, ac, av); + outlet_new((t_object *)x, &s_signal); + x->x_last = 0; + return (x); +} + +void deltaclip_tilde_setup(void) +{ + deltaclip_class = class_new(gensym("deltaclip~"), + (t_newmethod)deltaclip_new, 0, + sizeof(t_deltaclip), 0, A_GIMME, 0); + sic_setup(deltaclip_class, deltaclip_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/edge.c b/cyclone/sickle/edge.c new file mode 100644 index 0000000..b206f6b --- /dev/null +++ b/cyclone/sickle/edge.c @@ -0,0 +1,106 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _edge +{ + t_sic x_sic; + t_float x_last; + int x_zeroleft; + int x_zerohit; + t_outlet *x_out2; + t_clock *x_clock; +} t_edge; + +static t_class *edge_class; + +static void edge_tick(t_edge *x) +{ + /* CHECKED both may fire simultaneously */ + if (x->x_zeroleft) + { + outlet_bang(((t_object *)x)->ob_outlet); + x->x_zeroleft = 0; + } + if (x->x_zerohit) + { + outlet_bang(x->x_out2); + x->x_zerohit = 0; + } +} + +static t_int *edge_perform(t_int *w) +{ + t_edge *x = (t_edge *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float last = x->x_last; + while (nblock--) + { + float f = *in++; + if (last == 0.) + { + if (f != 0.) + { + x->x_zeroleft = 1; + if (x->x_zerohit) + { + clock_delay(x->x_clock, 0); + x->x_last = in[nblock - 1]; + return (w + 4); + } + } + } + else + { + if (f == 0.) + { + x->x_zerohit = 1; + if (x->x_zeroleft) + { + clock_delay(x->x_clock, 0); + x->x_last = in[nblock - 1]; + return (w + 4); + } + } + } + last = f; + } + if (x->x_zeroleft || x->x_zerohit) clock_delay(x->x_clock, 0); + x->x_last = last; + return (w + 4); +} + +static void edge_dsp(t_edge *x, t_signal **sp) +{ + dsp_add(edge_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void edge_free(t_edge *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *edge_new(t_floatarg f) +{ + t_edge *x = (t_edge *)pd_new(edge_class); + x->x_last = 0.; /* CHECKED fires at startup */ + x->x_zeroleft = x->x_zerohit = 0; + outlet_new((t_object *)x, &s_bang); + x->x_out2 = outlet_new((t_object *)x, &s_bang); + x->x_clock = clock_new(x, (t_method)edge_tick); + return (x); +} + +void edge_tilde_setup(void) +{ + edge_class = class_new(gensym("edge~"), + (t_newmethod)edge_new, + (t_method)edge_free, + sizeof(t_edge), 0, + A_DEFFLOAT, 0); + sic_setup(edge_class, edge_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/frameaccum.c b/cyclone/sickle/frameaccum.c new file mode 100644 index 0000000..6038ae5 --- /dev/null +++ b/cyclone/sickle/frameaccum.c @@ -0,0 +1,71 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" +#include "sickle/sic.h" + +#define FRAMEACCUM_INISIZE 512 + +typedef struct _frameaccum +{ + t_sic x_sic; + int x_size; + t_float *x_frame; + t_float x_frameini[FRAMEACCUM_INISIZE]; +} t_frameaccum; + +static t_class *frameaccum_class; + +static t_int *frameaccum_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *frame = (t_float *)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) *out++ = (*frame++ += *in++); + return (w + 5); +} + +static void frameaccum_dsp(t_frameaccum *x, t_signal **sp) +{ + int nblock = sp[0]->s_n; + if (nblock > x->x_size) + x->x_frame = grow_nodata(&nblock, &x->x_size, x->x_frame, + FRAMEACCUM_INISIZE, x->x_frameini, + sizeof(*x->x_frame)); + memset(x->x_frame, 0, nblock * sizeof(*x->x_frame)); /* CHECKED */ + dsp_add(frameaccum_perform, 4, nblock, x->x_frame, + sp[0]->s_vec, sp[1]->s_vec); +} + +static void frameaccum_free(t_frameaccum *x) +{ + if (x->x_frame != x->x_frameini) + freebytes(x->x_frame, x->x_size * sizeof(*x->x_frame)); +} + +static void *frameaccum_new(t_symbol *s, int ac, t_atom *av) +{ + t_frameaccum *x = (t_frameaccum *)pd_new(frameaccum_class); + int size; + x->x_size = FRAMEACCUM_INISIZE; + x->x_frame = x->x_frameini; + if ((size = sys_getblksize()) > FRAMEACCUM_INISIZE) + x->x_frame = grow_nodata(&size, &x->x_size, x->x_frame, + FRAMEACCUM_INISIZE, x->x_frameini, + sizeof(*x->x_frame)); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void frameaccum_tilde_setup(void) +{ + frameaccum_class = class_new(gensym("frameaccum~"), + (t_newmethod)frameaccum_new, + (t_method)frameaccum_free, + sizeof(t_frameaccum), 0, 0); + sic_setup(frameaccum_class, frameaccum_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/framedelta.c b/cyclone/sickle/framedelta.c new file mode 100644 index 0000000..b898444 --- /dev/null +++ b/cyclone/sickle/framedelta.c @@ -0,0 +1,76 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" +#include "sickle/sic.h" + +#define FRAMEDELTA_INISIZE 512 + +typedef struct _framedelta +{ + t_sic x_sic; + int x_size; + t_float *x_frame; + t_float x_frameini[FRAMEDELTA_INISIZE]; +} t_framedelta; + +static t_class *framedelta_class; + +static t_int *framedelta_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *frame = (t_float *)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + float f = *in++; + *out++ = f - *frame; /* CHECKME */ + *frame++ = f; + } + return (w + 5); +} + +static void framedelta_dsp(t_framedelta *x, t_signal **sp) +{ + int nblock = sp[0]->s_n; + if (nblock > x->x_size) + x->x_frame = grow_nodata(&nblock, &x->x_size, x->x_frame, + FRAMEDELTA_INISIZE, x->x_frameini, + sizeof(*x->x_frame)); + memset(x->x_frame, 0, nblock * sizeof(*x->x_frame)); /* CHECKME */ + dsp_add(framedelta_perform, 4, nblock, x->x_frame, + sp[0]->s_vec, sp[1]->s_vec); +} + +static void framedelta_free(t_framedelta *x) +{ + if (x->x_frame != x->x_frameini) + freebytes(x->x_frame, x->x_size * sizeof(*x->x_frame)); +} + +static void *framedelta_new(t_symbol *s, int ac, t_atom *av) +{ + t_framedelta *x = (t_framedelta *)pd_new(framedelta_class); + int size; + x->x_size = FRAMEDELTA_INISIZE; + x->x_frame = x->x_frameini; + if ((size = sys_getblksize()) > FRAMEDELTA_INISIZE) + x->x_frame = grow_nodata(&size, &x->x_size, x->x_frame, + FRAMEDELTA_INISIZE, x->x_frameini, + sizeof(*x->x_frame)); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void framedelta_tilde_setup(void) +{ + framedelta_class = class_new(gensym("framedelta~"), + (t_newmethod)framedelta_new, + (t_method)framedelta_free, + sizeof(t_framedelta), 0, 0); + sic_setup(framedelta_class, framedelta_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/index.c b/cyclone/sickle/index.c new file mode 100644 index 0000000..036e6fb --- /dev/null +++ b/cyclone/sickle/index.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER: 'click' method */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +#define INDEX_MAXCHANNELS 4 /* LATER implement arsic resizing feature */ + +typedef struct _index +{ + t_arsic x_arsic; + int x_maxchannels; + int x_effchannel; /* effective channel (clipped reqchannel) */ + int x_reqchannel; /* requested channel */ +} t_index; + +static t_class *index_class; + +static void index_set(t_index *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); +} + +static t_int *index_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + t_float *out = (t_float *)(w[4]); + if (sic->s_playable) + { + t_index *x = (t_index *)sic; + t_float *xin = (t_float *)(w[3]); + int index, maxindex = sic->s_vecsize - 1; + t_float *vp = sic->s_vectors[x->x_effchannel]; + if (vp) /* handle array swapping on the fly via ft1 */ + { + while (nblock--) + { + index = (int)(*xin++ + 0.5); + if (index < 0) + index = 0; + else if (index > maxindex) + index = maxindex; + *out++ = vp[index]; + } + } + else while (nblock--) *out++ = 0; + } + else while (nblock--) *out++ = 0; + return (w + 5); +} + +static void index_ft1(t_index *x, t_floatarg f) +{ + if ((x->x_reqchannel = (f > 1 ? (int)f - 1 : 0)) > x->x_maxchannels) + x->x_effchannel = x->x_maxchannels - 1; + else + x->x_effchannel = x->x_reqchannel; +} + +static void index_dsp(t_index *x, t_signal **sp) +{ + t_arsic *sic = (t_arsic *)x; + arsic_dsp(sic, sp, index_perform, sic->s_mononame != 0); +} + +static void index_free(t_index *x) +{ + arsic_free((t_arsic *)x); +} + +static void *index_new(t_symbol *s, t_floatarg f) +{ + int ch = (f > 0 ? (int)f : 0); + /* two signals: index input, value output */ + t_index *x = (t_index *)arsic_new(index_class, s, + (ch ? INDEX_MAXCHANNELS : 0), 2, 0); + if (x) + { + if (ch > INDEX_MAXCHANNELS) + ch = INDEX_MAXCHANNELS; + x->x_maxchannels = (ch ? INDEX_MAXCHANNELS : 1); + x->x_effchannel = x->x_reqchannel = (ch ? ch - 1 : 0); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + } + return (x); +} + +void index_tilde_setup(void) +{ + index_class = class_new(gensym("index~"), + (t_newmethod)index_new, + (t_method)index_free, + sizeof(t_index), 0, + A_DEFSYM, A_DEFFLOAT, 0); + arsic_setup(index_class, index_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(index_class, (t_method)index_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(index_class, (t_method)index_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/kink.c b/cyclone/sickle/kink.c new file mode 100644 index 0000000..86bc81d --- /dev/null +++ b/cyclone/sickle/kink.c @@ -0,0 +1,62 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKED negative float in 2nd inlet: "illegal slope value %f", + but no complaints for signal input -- this is impossible in Pd. + The only thing we could do (and a bit stupid one) would be to + clock this exception out from the perf routine. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define KINK_DEFSLOPE 1.0 + +typedef t_sic t_kink; +static t_class *kink_class; + +static t_int *kink_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + float iph = *in1++; + float slope = *in2++; + float oph = iph * slope; + if (oph > .5) + { + slope = 1. / (slope + slope); /* x(y=.5) */ + if (slope == 1.) + *out++ = 0; /* CHECKED */ + else + *out++ = (iph - slope) / (2. - (slope + slope)) + .5; + } + else *out++ = oph; + } + return (w + 5); +} + +static void kink_dsp(t_kink *x, t_signal **sp) +{ + dsp_add(kink_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *kink_new(t_symbol *s, int ac, t_atom *av) +{ + t_kink *x = (t_kink *)pd_new(kink_class); + sic_inlet((t_sic *)x, 1, KINK_DEFSLOPE, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void kink_tilde_setup(void) +{ + kink_class = class_new(gensym("kink~"), + (t_newmethod)kink_new, 0, + sizeof(t_kink), 0, A_GIMME, 0); + sic_setup(kink_class, kink_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/linedrive.c b/cyclone/sickle/linedrive.c new file mode 100644 index 0000000..8b133ab --- /dev/null +++ b/cyclone/sickle/linedrive.c @@ -0,0 +1,73 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKME polarity */ + +#include <math.h> +#include "m_pd.h" + +#if defined(NT) || defined(MACOSX) +#define logf log +#define expf exp +#endif + +static t_class *linedrive_class; + +typedef struct _linedrive +{ + t_object x_ob; + t_float x_maxin; + t_float x_maxout; + t_float x_expcoef; + t_float x_lincoef; + t_atom x_vec[2]; + int x_linear; +} t_linedrive; + +static void linedrive_float(t_linedrive *x, t_floatarg f) +{ + float outval = f - x->x_maxin; + if (outval >= 0) + outval = x->x_maxout; /* CHECKED */ + else if (x->x_linear) + outval = x->x_maxout + outval * x->x_lincoef; + else + outval = expf(outval * x->x_expcoef) * x->x_maxout; + SETFLOAT(x->x_vec, outval); + outlet_list(((t_object *)x)->ob_outlet, 0, 2, x->x_vec); +} + +static void *linedrive_new(t_floatarg maxin, t_floatarg maxout, + t_floatarg curve, t_floatarg deltime) +{ + t_linedrive *x = (t_linedrive *)pd_new(linedrive_class); + x->x_maxin = (maxin < 1.0e-20f && maxin > -1e-20f ? 0 : maxin); + x->x_maxout = maxout; + if (curve < 1.0e-20f) curve = 1.0; /* a bug in msp? */ + if (curve == 1.0) + { + x->x_expcoef = 0; + x->x_lincoef = (x->x_maxin == 0 ? 0 : x->x_maxout / x->x_maxin); + x->x_linear = 1; + } + else { + x->x_expcoef = logf(curve); + x->x_lincoef = 0; + x->x_linear = 0; + } + SETFLOAT(&x->x_vec[1], deltime); /* CHECKED: any value accepted */ + floatinlet_new((t_object *)x, &x->x_vec[1].a_w.w_float); + outlet_new((t_object *)x, &s_list); + return (x); +} + +void linedrive_setup(void) +{ + linedrive_class = class_new(gensym("linedrive"), + (t_newmethod)linedrive_new, 0, + sizeof(t_linedrive), 0, + A_DEFFLOAT, A_DEFFLOAT, + A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(linedrive_class, linedrive_float); +} diff --git a/cyclone/sickle/log.c b/cyclone/sickle/log.c new file mode 100644 index 0000000..74e3e40 --- /dev/null +++ b/cyclone/sickle/log.c @@ -0,0 +1,74 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define logf log +#endif + +#define LOG_MININPUT 1e-10 /* CHECKED */ + +typedef struct _log +{ + t_sic x_sic; + t_float x_rcplogbase; /* LATER consider using double (and log()) */ +} t_log; + +static t_class *log_class; + +static void log_ft1(t_log *x, t_floatarg f) +{ + x->x_rcplogbase = (f == 0. ? 1. : /* CHECKED no protection against NaNs */ + (f == 1. ? 0. : /* CHECKED */ + 1. / logf(f))); +} + +static t_int *log_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + t_float rcplogbase = *(t_float *)(w[4]); + if (rcplogbase != 0.) + { + while (nblock--) + { + float f = *in++; + if (f < LOG_MININPUT) + f = LOG_MININPUT; /* CHECKED */ + *out++ = logf(f) * rcplogbase; + } + } + else while (nblock--) *out++ = 0.; + return (w + 5); +} + +static void log_dsp(t_log *x, t_signal **sp) +{ + dsp_add(log_perform, 4, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec, + &x->x_rcplogbase); +} + +static void *log_new(t_floatarg f) +{ + t_log *x = (t_log *)pd_new(log_class); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_signal); + log_ft1(x, f); + return (x); +} + +void log_tilde_setup(void) +{ + log_class = class_new(gensym("log~"), + (t_newmethod)log_new, 0, + sizeof(t_log), 0, A_DEFFLOAT, 0); + sic_setup(log_class, log_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(log_class, (t_method)log_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/lookup.c b/cyclone/sickle/lookup.c new file mode 100644 index 0000000..1c6a8af --- /dev/null +++ b/cyclone/sickle/lookup.c @@ -0,0 +1,94 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER reconsider making float/int conversions + more compatible (and less useful). */ + +#include "m_pd.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +typedef t_arsic t_lookup; +static t_class *lookup_class; + +#define LOOKUP_DEFSIZE 512 + +static void lookup_set(t_lookup *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); +} + +static t_int *lookup_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + t_float *out = (t_float *)(w[6]); + if (sic->s_playable) + { + t_float *xin = (t_float *)(w[3]); + t_float *oin = (t_float *)(w[4]); + t_float *sin = (t_float *)(w[5]); + int vecsize = sic->s_vecsize; + t_float *vec = sic->s_vectors[0]; /* playable implies nonzero (mono) */ + while (nblock--) + { + float off = *oin++; /* msp: converted to int (if not a signal) */ + int siz = (int)*sin++ - 1; /* msp: converted to int (signal too) */ + float pos = (siz > 0 ? off + siz * (*xin++ + 1.0) * 0.5 : off); + int ndx = (int)pos; + int ndx1 = ndx + 1; + if (ndx1 > 0 && ndx1 < vecsize) + { + float val = vec[ndx]; + *out++ = val + (vec[ndx1] - val) * (pos - ndx); + } + /* CHECKED: */ + else if (ndx1 == 0) *out++ = *vec * (pos + 1.0); + else if (ndx1 == vecsize) *out++ = vec[ndx] * (ndx1 - pos); + else *out++ = 0; + } + } + else while (nblock--) *out++ = 0; + return (w + 7); +} + +static void lookup_dsp(t_lookup *x, t_signal **sp) +{ + arsic_dsp((t_arsic *)x, sp, lookup_perform, 1); +} + +static void lookup_free(t_lookup *x) +{ + arsic_free((t_arsic *)x); +} + +static void *lookup_new(t_symbol *s, t_floatarg f1, t_floatarg f2) +{ + /* CHECKED: lookup~ always uses the first channel in a multi-channel buffer~ + (as the refman says). */ + /* three auxiliary signals: amplitude, offset and size inputs */ + t_lookup *x = (t_lookup *)arsic_new(lookup_class, s, 0, 0, 3); + if (x) + { + arsic_setminsize((t_arsic *)x, 2); + if (f1 < 0) f1 = 0; + if (f2 <= 0) f2 = LOOKUP_DEFSIZE; + sic_newinlet((t_sic *)x, f1); + sic_newinlet((t_sic *)x, f2); + outlet_new((t_object *)x, &s_signal); + } + return (x); +} + +void lookup_tilde_setup(void) +{ + lookup_class = class_new(gensym("lookup~"), + (t_newmethod)lookup_new, + (t_method)lookup_free, + sizeof(t_lookup), 0, + A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); + arsic_setup(lookup_class, lookup_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(lookup_class, (t_method)lookup_set, + gensym("set"), A_SYMBOL, 0); +} diff --git a/cyclone/sickle/minmax.c b/cyclone/sickle/minmax.c new file mode 100644 index 0000000..5bd0e39 --- /dev/null +++ b/cyclone/sickle/minmax.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _minmax +{ + t_sic x_sic; + t_float x_min; + t_float x_max; + t_outlet *x_minout; + t_outlet *x_maxout; +} t_minmax; + +static t_class *minmax_class; + +static void minmax_bang(t_minmax *x) +{ + outlet_float(x->x_maxout, x->x_max); + outlet_float(x->x_minout, x->x_min); +} + +static void minmax_reset(t_minmax *x) +{ + x->x_min = x->x_max = 0; /* CHECKME */ +} + +static t_int *minmax_perform(t_int *w) +{ + t_minmax *x = (t_minmax *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *outmin = (t_float *)(w[4]); + t_float *outmax = (t_float *)(w[5]); + t_float fmin = x->x_min; + t_float fmax = x->x_max; + while (nblock--) + { + t_float f = *in++; + if (f < fmin) fmin = f; + else if (f > fmax) fmax = f; + *outmin++ = fmin; + *outmax++ = fmax; + } + x->x_min = fmin; + x->x_max = fmax; + return (w + 6); +} + +static void minmax_dsp(t_minmax *x, t_signal **sp) +{ + dsp_add(minmax_perform, 5, x, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); +} + +static void *minmax_new(void) +{ + t_minmax *x = (t_minmax *)pd_new(minmax_class); + outlet_new((t_object *)x, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_minout = outlet_new((t_object *)x, &s_float); + x->x_maxout = outlet_new((t_object *)x, &s_float); + minmax_reset(x); + return (x); +} + +void minmax_tilde_setup(void) +{ + minmax_class = class_new(gensym("minmax~"), + (t_newmethod)minmax_new, 0, + sizeof(t_minmax), 0, 0); + sic_setup(minmax_class, minmax_dsp, SIC_FLOATTOSIGNAL); + class_addbang(minmax_class, minmax_bang); + class_addmethod(minmax_class, (t_method)minmax_reset, + gensym("reset"), 0); +} diff --git a/cyclone/sickle/peakamp.c b/cyclone/sickle/peakamp.c new file mode 100644 index 0000000..67d1093 --- /dev/null +++ b/cyclone/sickle/peakamp.c @@ -0,0 +1,107 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _peakamp +{ + t_sic x_sic; + t_float x_value; + int x_nwait; + int x_nleft; + int x_precount; + float x_waittime; + float x_ksr; + t_clock *x_clock; +} t_peakamp; + +static t_class *peakamp_class; + +static void peakamp_tick(t_peakamp *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_value); + x->x_value = 0; + if ((x->x_nleft = x->x_nwait - x->x_precount) < 0) /* CHECKME */ + x->x_nleft = 0; +} + +static void peakamp_bang(t_peakamp *x) +{ + peakamp_tick(x); /* CHECKME */ +} + +static void peakamp_ft1(t_peakamp *x, t_floatarg f) +{ + if ((x->x_waittime = f) < 0.) + x->x_waittime = 0.; + if ((x->x_nwait = (int)(x->x_waittime * x->x_ksr)) < 0) + x->x_nwait = 0; +} + +static t_int *peakamp_perform(t_int *w) +{ + t_peakamp *x = (t_peakamp *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float value = x->x_value; + if (x->x_nwait) + { + if (x->x_nleft < nblock) + { + clock_delay(x->x_clock, 0); + x->x_precount = nblock - x->x_nleft; + x->x_nleft = 0; /* LATER rethink */ + } + else x->x_nleft -= nblock; + } + while (nblock--) + { + t_float f = *in++; + if (f > value) + value = f; + else if (f < -value) + value = -f; + } + x->x_value = value; + return (w + 4); +} + +static void peakamp_dsp(t_peakamp *x, t_signal **sp) +{ + x->x_ksr = sp[0]->s_sr * 0.001; + x->x_nwait = (int)(x->x_waittime * x->x_ksr); + dsp_add(peakamp_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void peakamp_free(t_peakamp *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *peakamp_new(t_floatarg f) +{ + t_peakamp *x = (t_peakamp *)pd_new(peakamp_class); + x->x_value = 0.; + x->x_nleft = 0; + x->x_ksr = sys_getsr() * 0.001; + peakamp_ft1(x, f); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_clock = clock_new(x, (t_method)peakamp_tick); + return (x); +} + +void peakamp_tilde_setup(void) +{ + peakamp_class = class_new(gensym("peakamp~"), + (t_newmethod)peakamp_new, + (t_method)peakamp_free, + sizeof(t_peakamp), 0, + A_DEFFLOAT, 0); + sic_setup(peakamp_class, peakamp_dsp, SIC_FLOATTOSIGNAL); + class_addbang(peakamp_class, peakamp_bang); + class_addmethod(peakamp_class, (t_method)peakamp_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/peek.c b/cyclone/sickle/peek.c new file mode 100644 index 0000000..7397577 --- /dev/null +++ b/cyclone/sickle/peek.c @@ -0,0 +1,147 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER: 'click' method */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +#define PEEK_MAXCHANNELS 4 /* LATER implement arsic resizing feature */ + +typedef struct _peek +{ + t_arsic x_arsic; + int x_maxchannels; + int x_effchannel; /* effective channel (clipped reqchannel) */ + int x_reqchannel; /* requested channel */ + int x_clipmode; + int x_pokemode; + t_float x_value; + t_clock *x_clock; + double x_clocklasttick; + int x_clockset; +} t_peek; + +static t_class *peek_class; + +static void peek_tick(t_peek *x) +{ + arsic_redraw((t_arsic *)x); /* LATER redraw only dirty channel(s!) */ + x->x_clockset = 0; + x->x_clocklasttick = clock_getsystime(); +} + +static void peek_set(t_peek *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); +} + +#define peek_doclip(f) (f < -1. ? -1. : (f > 1. ? 1. : f)) + +/* CHECKED refman error: ``if the number received in the left inlet + specifies a sample index that does not exist in the buffer~ object's + currently allocated memory, nothing happens.'' This is plainly wrong, + at least for max/msp 4.0.7 bundle: the index is clipped (just like + in tabread/tabwrite). As a kind of an experiment, lets make this + the refman's way... */ +static void peek_float(t_peek *x, t_float f) +{ + t_arsic *sic = (t_arsic *)x; + t_float *vp; + arsic_validate(sic, 0); /* LATER rethink (efficiency, and complaining) */ + if (vp = sic->s_vectors[x->x_effchannel]) + { + int ndx = (int)f; + if (vp && ndx >= 0 && ndx < sic->s_vecsize) + { + if (x->x_pokemode) + { + double timesince; + t_float f = x->x_value; + vp[ndx] = (x->x_clipmode ? peek_doclip(f) : f); + x->x_pokemode = 0; + timesince = clock_gettimesince(x->x_clocklasttick); + if (timesince > 1000) peek_tick(x); + else if (!x->x_clockset) + { + clock_delay(x->x_clock, 1000 - timesince); + x->x_clockset = 1; + } + } + /* CHECKED: output not clipped */ + else outlet_float(((t_object *)x)->ob_outlet, vp[ndx]); + } + } +} + +static void peek_ft1(t_peek *x, t_floatarg f) +{ + x->x_value = f; + x->x_pokemode = 1; + /* CHECKED: poke-mode is reset only after receiving left inlet input + -- it is kept across 'ft2', 'clip', and 'set' inputs. */ +} + +static void peek_ft2(t_peek *x, t_floatarg f) +{ + if ((x->x_reqchannel = (f > 1 ? (int)f - 1 : 0)) > x->x_maxchannels) + x->x_effchannel = x->x_maxchannels - 1; + else + x->x_effchannel = x->x_reqchannel; +} + +static void peek_clip(t_peek *x, t_floatarg f) +{ + x->x_clipmode = ((int)f != 0); +} + +static void peek_free(t_peek *x) +{ + if (x->x_clock) clock_free(x->x_clock); + arsic_free((t_arsic *)x); +} + +static void *peek_new(t_symbol *s, t_floatarg f1, t_floatarg f2) +{ + int ch = (f1 > 0 ? (int)f1 : 0); + t_peek *x = (t_peek *)arsic_new(peek_class, s, + (ch ? PEEK_MAXCHANNELS : 0), 0, 0); + if (x) + { + if (ch > PEEK_MAXCHANNELS) + ch = PEEK_MAXCHANNELS; + x->x_maxchannels = (ch ? PEEK_MAXCHANNELS : 1); + x->x_effchannel = x->x_reqchannel = (ch ? ch - 1 : 0); + /* CHECKED (refman error) clipping is disabled by default */ + x->x_clipmode = ((int)f2 != 0); + x->x_pokemode = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft2")); + outlet_new((t_object *)x, &s_float); + x->x_clock = clock_new(x, (t_method)peek_tick); + x->x_clocklasttick = clock_getsystime(); + x->x_clockset = 0; + } + return (x); +} + +void peek_tilde_setup(void) +{ + peek_class = class_new(gensym("peek~"), + (t_newmethod)peek_new, + (t_method)peek_free, + sizeof(t_peek), 0, + A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, 0); + class_addfloat(peek_class, peek_float); + class_addmethod(peek_class, (t_method)peek_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(peek_class, (t_method)peek_ft1, + gensym("ft1"), A_FLOAT, 0); + class_addmethod(peek_class, (t_method)peek_ft2, + gensym("ft2"), A_FLOAT, 0); + class_addmethod(peek_class, (t_method)peek_clip, + gensym("clip"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/phasewrap.c b/cyclone/sickle/phasewrap.c new file mode 100644 index 0000000..535d5e8 --- /dev/null +++ b/cyclone/sickle/phasewrap.c @@ -0,0 +1,131 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" + +typedef struct _phasewrap +{ + t_sic x_sic; + int x_algo; +} t_phasewrap; + +static t_class *phasewrap_class; + +static t_int *phasewrap_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + t_shared_wrappy wrappy; + while (nblock--) + { + /* FIXME here we have pi -> pi, 3pi -> -pi, -pi -> -pi, -3pi -> pi, + while in msp it is pi -> -pi, 3pi -> -pi, -pi -> pi, -3pi -> pi */ + + double dnorm = *in++ * (1. / SHARED_2PI); + wrappy.w_d = dnorm + SHARED_UNITBIT0; + /* Speeding up the int-to-double conversion below would be nice, + but all attempts failed. Even this is slower (which works only + for nonnegative input): + + wrappy.w_i[SHARED_HIOFFSET] = SHARED_UNITBIT0_HIPART; + *out++ = (dnorm - (wrappy.w_d - SHARED_UNITBIT0)) * SHARED_2PI; + */ + dnorm -= wrappy.w_i[SHARED_LOWOFFSET]; + *out++ = dnorm * SHARED_2PI; + } + return (w + 4); +} + +/* This is the slowest algo. It is slower than fmod in all cases, + except for input being zero. */ +static t_int *phasewrap_perform1(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + double dnorm; + if (f < -SHARED_PI) + { + dnorm = (double)f * (1. / SHARED_2PI) + .5; + *out++ = (dnorm - (int)dnorm) * SHARED_2PI + SHARED_PI; + } + else if (f > SHARED_PI) + { + dnorm = (double)f * (1. / SHARED_2PI) + .5; + *out++ = (dnorm - (int)dnorm) * SHARED_2PI - SHARED_PI; + } + else *out++ = f; + } + return (w + 4); +} + +static t_int *phasewrap_perform2(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + double dnorm = *in++ + SHARED_PI; + if (dnorm < 0) + *out++ = SHARED_PI - fmod(-dnorm, SHARED_2PI); + else + *out++ = fmod(dnorm, SHARED_2PI) - SHARED_PI; + } + return (w + 4); +} + +static void phasewrap_dsp(t_phasewrap *x, t_signal **sp) +{ + switch (x->x_algo) + { + case 1: + dsp_add(phasewrap_perform1, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + break; + case 2: + dsp_add(phasewrap_perform2, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + break; + default: + dsp_add(phasewrap_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); + } +} + +static void phasewrap__algo(t_phasewrap *x, t_floatarg f) +{ + x->x_algo = f; +} + +static void *phasewrap_new(t_symbol *s, int ac, t_atom *av) +{ + t_phasewrap *x = (t_phasewrap *)pd_new(phasewrap_class); + if (s == gensym("_phasewrap1~")) + x->x_algo = 1; + else if (s == gensym("_phasewrap2~")) + x->x_algo = 2; + else + x->x_algo = 0; + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void phasewrap_tilde_setup(void) +{ + phasewrap_class = class_new(gensym("phasewrap~"), + (t_newmethod)phasewrap_new, 0, + sizeof(t_phasewrap), 0, A_GIMME, 0); + class_addcreator((t_newmethod)phasewrap_new, + gensym("_phasewrap1~"), A_GIMME, 0); + class_addcreator((t_newmethod)phasewrap_new, + gensym("_phasewrap2~"), A_GIMME, 0); + sic_setup(phasewrap_class, phasewrap_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(phasewrap_class, (t_method)phasewrap__algo, + gensym("_algo"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/play.c b/cyclone/sickle/play.c new file mode 100644 index 0000000..9d2c303 --- /dev/null +++ b/cyclone/sickle/play.c @@ -0,0 +1,122 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +/* CHECKME (the refman): if the buffer~ has more channels, channels are mixed */ + +typedef t_arsic t_play; +static t_class *play_class; + +static void play_set(t_play *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); +} + +/* LATER optimize */ +static t_int *play_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + int nch = sic->s_nchannels; + t_int *outp = w + 4; + if (sic->s_playable) + { + t_play *x = (t_play *)sic; + t_float *xin = (t_float *)(w[3]); + int vecsize = sic->s_vecsize; + t_float **vectable = sic->s_vectors; + float ksr = sic->s_ksr; + int nointerp = 0; + int maxindex = (nointerp ? vecsize - 1 : vecsize - 3); + int iblock; + + for (iblock = 0; iblock < nblock; iblock++) + { + float phase = *xin++ * ksr; + int ndx; + int ch = nch; + float frac, a, b, c, d, cminusb; + if (phase < 0 || phase > maxindex) + phase = 0; /* CHECKED: a value 0, not ndx 0 */ + ndx = (int)phase; + /* CHECKME: what kind of interpolation? (CHECKED: multi-point) */ + if (ndx < 1) + ndx = 1, frac = 0; + else if (ndx > maxindex) + ndx = maxindex, frac = 1; + else frac = phase - ndx; + while (ch--) + { + t_float *vp = vectable[ch]; + t_float *out = (t_float *)(outp[ch]); + if (vp) + { + vp += ndx; + a = vp[-1]; + b = vp[0]; + c = vp[1]; + d = vp[2]; + cminusb = c-b; + out[iblock] = b + frac * ( + cminusb - 0.1666667f * (1. - frac) * ( + (d - a - 3.0f * cminusb) * frac + + (d + 2.0f * a - 3.0f * b) + ) + ); + } + else out[iblock] = 0; + } + } + } + else + { + int ch = nch; + while (ch--) + { + t_float *out = (t_float *)outp[ch]; + int n = nblock; + while (n--) *out++ = 0; + } + } + return (w + sic->s_nperfargs + 1); +} + +static void play_dsp(t_play *x, t_signal **sp) +{ + arsic_dsp((t_arsic *)x, sp, play_perform, 1); +} + +static void play_free(t_play *x) +{ + arsic_free((t_arsic *)x); +} + +static void *play_new(t_symbol *s, t_floatarg f) +{ + /* one auxiliary signal: position input */ + t_play *x = (t_play *)arsic_new(play_class, s, (int)f, 0, 1); + if (x) + { + int nch = arsic_getnchannels((t_arsic *)x); + while (nch--) + outlet_new((t_object *)x, &s_signal); + } + return (x); +} + +void play_tilde_setup(void) +{ + play_class = class_new(gensym("play~"), + (t_newmethod)play_new, + (t_method)play_free, + sizeof(t_play), 0, + A_DEFSYM, A_DEFFLOAT, 0); + arsic_setup(play_class, play_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(play_class, (t_method)play_set, + gensym("set"), A_SYMBOL, 0); +} diff --git a/cyclone/sickle/poltocar.c b/cyclone/sickle/poltocar.c new file mode 100644 index 0000000..8d7f94c --- /dev/null +++ b/cyclone/sickle/poltocar.c @@ -0,0 +1,79 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "unstable/fragile.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sinf sin +#define cosf cos +#endif + +typedef struct _poltocar +{ + t_sic x_sic; + t_outlet *x_out2; +} t_poltocar; + +static t_class *poltocar_class; + +static t_int *poltocar_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out1 = (t_float *)(w[4]); + t_float *out2 = (t_float *)(w[5]); + while (nblock--) + { + float am = *in1++, ph = *in2++; + *out1++ = am * cosf(ph); + *out2++ = -am * sinf(ph); /* CHECKED */ + } + return (w + 6); +} + +static t_int *poltocar_perform_noimag(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out1 = (t_float *)(w[4]); + while (nblock--) + { + float am = *in1++, ph = *in2++; + *out1++ = am * cosf(ph); + } + return (w + 5); +} + +static void poltocar_dsp(t_poltocar *x, t_signal **sp) +{ + if (fragile_outlet_connections(x->x_out2)) + dsp_add(poltocar_perform, 5, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); + else + dsp_add(poltocar_perform_noimag, 4, sp[0]->s_n, sp[0]->s_vec, + sp[1]->s_vec, sp[2]->s_vec); +} + +static void *poltocar_new(void) +{ + t_poltocar *x = (t_poltocar *)pd_new(poltocar_class); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + x->x_out2 = outlet_new((t_object *)x, &s_signal); + return (x); +} + +void poltocar_tilde_setup(void) +{ + poltocar_class = class_new(gensym("poltocar~"), + (t_newmethod)poltocar_new, 0, + sizeof(t_poltocar), 0, 0); + sic_setup(poltocar_class, poltocar_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/pow.c b/cyclone/sickle/pow.c new file mode 100644 index 0000000..11cd508 --- /dev/null +++ b/cyclone/sickle/pow.c @@ -0,0 +1,54 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define powf pow +#endif + +typedef t_sic t_pow; +static t_class *pow_class; + +static t_int *pow_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in1 = (t_float *)(w[2]); + t_float *in2 = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + while (nblock--) + { + float f1 = *in1++; + float f2 = *in2++; + /* CHECKED arg order, no protection against NaNs (negative base), + under-, and overflows */ + *out++ = powf(f2, f1); + } + return (w + 5); +} + +static void pow_dsp(t_pow *x, t_signal **sp) +{ + dsp_add(pow_perform, 4, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *pow_new(t_floatarg f) +{ + t_pow *x = (t_pow *)pd_new(pow_class); + sic_newinlet((t_sic *)x, f); /* CHECKED default 0 */ + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void pow_tilde_setup(void) +{ + pow_class = class_new(gensym("pow~"), + (t_newmethod)pow_new, 0, + sizeof(t_pow), 0, A_DEFFLOAT, 0); + sic_setup(pow_class, pow_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/rampsmooth.c b/cyclone/sickle/rampsmooth.c new file mode 100644 index 0000000..c2023d8 --- /dev/null +++ b/cyclone/sickle/rampsmooth.c @@ -0,0 +1,206 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define RAMPSMOOTH_GEOMETRIC /* geometric series (same as slide~) CHECKED */ +#ifndef RAMPSMOOTH_GEOMETRIC +#define RAMPSMOOTH_LINEAR +#endif +#define RAMPSMOOTH_DEFNUP 0. +#define RAMPSMOOTH_DEFNDOWN 0. + +typedef struct _rampsmooth +{ + t_sic x_sic; + int x_nup; + int x_ndown; + double x_upcoef; + double x_downcoef; + t_float x_last; +#ifdef RAMPSMOOTH_LINEAR + t_float x_target; + double x_incr; + int x_nleft; +#endif +} t_rampsmooth; + +static t_class *rampsmooth_class; + +#ifdef RAMPSMOOTH_LINEAR +/* this is a true linear ramper */ +static t_int *rampsmooth_perform(t_int *w) +{ + t_rampsmooth *x = (t_rampsmooth *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float last = x->x_last; + t_float target = x->x_target; + double incr = x->x_incr; + int nleft = x->x_nleft; + while (nblock--) + { + t_float f = *in++; + if (f != target) + { + target = f; + if (f > last) + { + if (x->x_nup > 1) + { + incr = (f - last) * x->x_upcoef; + nleft = x->x_nup; + *out++ = (last += incr); + continue; + } + } + else if (f < last) + { + if (x->x_ndown > 1) + { + incr = (f - last) * x->x_downcoef; + nleft = x->x_ndown; + *out++ = (last += incr); + continue; + } + } + incr = 0.; + nleft = 0; + *out++ = last = f; + } + else if (nleft > 0) + { + *out++ = (last += incr); + if (--nleft == 0) + { + incr = 0.; + last = target; + } + } + else *out++ = target; + } + x->x_last = last; + x->x_target = target; + x->x_incr = incr; + x->x_nleft = nleft; + return (w + 5); +} + +#else + +/* this ramper generates a geometric series output for a single step input */ +static t_int *rampsmooth_perform(t_int *w) +{ + t_rampsmooth *x = (t_rampsmooth *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + t_float last = x->x_last; + while (nblock--) + { + t_float f = *in++; + if (f > last) + { + if (x->x_nup > 1) + { + *out++ = (last += (f - last) * x->x_upcoef); + continue; + } + } + else if (f < last) + { + if (x->x_ndown > 1) + { + *out++ = (last += (f - last) * x->x_downcoef); + continue; + } + } + *out++ = last = f; + } + x->x_last = last; + return (w + 5); +} +#endif + +static void rampsmooth_dsp(t_rampsmooth *x, t_signal **sp) +{ + dsp_add(rampsmooth_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void rampsmooth_rampup(t_rampsmooth *x, t_floatarg f) +{ + int i = (int)f; + if (i > 1) /* CHECKME if 1 and 0 differ in any way */ + { + x->x_nup = i; + x->x_upcoef = 1. / (float)i; + } + else + { + x->x_nup = 0; + x->x_upcoef = 0.; + } +} + +static void rampsmooth_rampdown(t_rampsmooth *x, t_floatarg f) +{ + int i = (int)f; + if (i > 1) /* CHECKME if 1 and 0 differ in any way */ + { + x->x_ndown = i; + x->x_downcoef = 1. / (float)i; + } + else + { + x->x_ndown = 0; + x->x_downcoef = 0.; + } +} + +/* CHECKED */ +static void rampsmooth_ramp(t_rampsmooth *x, t_floatarg f) +{ + rampsmooth_rampup(x, f); + rampsmooth_rampdown(x, f); +} + +static void *rampsmooth_new(t_symbol *s, int ac, t_atom *av) +{ + t_rampsmooth *x = (t_rampsmooth *)pd_new(rampsmooth_class); + float f1 = RAMPSMOOTH_DEFNUP; + float f2 = RAMPSMOOTH_DEFNDOWN; + if (ac && av->a_type == A_FLOAT) + { + f1 = av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + f2 = av->a_w.w_float; + } + rampsmooth_rampup(x, f1); + rampsmooth_rampdown(x, f2); + x->x_last = 0.; +#ifdef RAMPSMOOTH_LINEAR + x->x_target = 0.; + x->x_incr = 0.; + x->x_nleft = 0; +#endif + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void rampsmooth_tilde_setup(void) +{ + rampsmooth_class = class_new(gensym("rampsmooth~"), + (t_newmethod)rampsmooth_new, 0, + sizeof(t_rampsmooth), 0, A_GIMME, 0); + sic_setup(rampsmooth_class, rampsmooth_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(rampsmooth_class, (t_method)rampsmooth_rampup, + gensym("rampup"), A_FLOAT, 0); + class_addmethod(rampsmooth_class, (t_method)rampsmooth_rampdown, + gensym("rampdown"), A_FLOAT, 0); + class_addmethod(rampsmooth_class, (t_method)rampsmooth_ramp, + gensym("ramp"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/rand.c b/cyclone/sickle/rand.c new file mode 100644 index 0000000..146cbc9 --- /dev/null +++ b/cyclone/sickle/rand.c @@ -0,0 +1,95 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is a compilation of phasor~ and noise~ code from d_osc.c. */ + +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" + +typedef struct _rand +{ + t_sic x_sic; + t_float x_rate; + double x_lastphase; + double x_nextphase; + float x_rcpsr; + int x_state; + float x_target; + float x_scaling; /* LATER use phase increment */ +} t_rand; + +static t_class *rand_class; + +static t_int *rand_perform(t_int *w) +{ + t_rand *x = (t_rand *)(w[1]); + int nblock = (int)(w[2]); + t_float *rin = (t_float *)(w[3]); + t_float *out = (t_float *)(w[4]); + double lastph = x->x_lastphase; + double ph = x->x_nextphase; + double tfph = ph + SHARED_UNITBIT32; + t_shared_wrappy wrappy; + int32 normhipart; + float rcpsr = x->x_rcpsr; + float target = x->x_target; + float scaling = x->x_scaling; + + wrappy.w_d = SHARED_UNITBIT32; + normhipart = wrappy.w_i[SHARED_HIOFFSET]; + + while (nblock--) + { + float rate = *rin++; + if (ph > lastph) + { + int state = x->x_state; + float newtarget = ((float)((state & 0x7fffffff) - 0x40000000)) + * (float)(1.0 / 0x40000000); + x->x_state = state * 435898247 + 382842987; + x->x_scaling = scaling = target - newtarget; + x->x_target = target = newtarget; + } + *out++ = ph * scaling + target; + lastph = ph; + if (rate > 0) rate = -rate; + tfph += rate * rcpsr; + wrappy.w_d = tfph; + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + ph = wrappy.w_d - SHARED_UNITBIT32; + } + x->x_lastphase = lastph; + x->x_nextphase = ph; + return (w + 5); +} + +static void rand_dsp(t_rand *x, t_signal **sp) +{ + x->x_rcpsr = 1. / sp[0]->s_sr; + dsp_add(rand_perform, 4, x, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *rand_new(t_floatarg inirate) +{ + t_rand *x = (t_rand *)pd_new(rand_class); + /* borrowed from d_osc.c, LATER rethink */ + static int init = 307; + x->x_state = (init *= 1319); + x->x_lastphase = 0.; + x->x_nextphase = 1.; /* start from 0, force retargetting */ + x->x_target = x->x_scaling = 0; + x->x_rate = (inirate > 0 ? -inirate : 0); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void rand_tilde_setup(void) +{ + rand_class = class_new(gensym("rand~"), + (t_newmethod)rand_new, 0, + sizeof(t_rand), 0, + A_DEFFLOAT, 0); + sic_setup(rand_class, rand_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/record.c b/cyclone/sickle/record.c new file mode 100644 index 0000000..ba2e3b5 --- /dev/null +++ b/cyclone/sickle/record.c @@ -0,0 +1,242 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +typedef struct _record +{ + t_arsic x_arsic; + float x_startpoint; /* the inputs */ + float x_endpoint; + int x_appendmode; + int x_loopmode; + int x_startindex; + int x_endindex; /* (one past last record position) */ + int x_pauseindex; + int x_phase; /* writing head */ + float x_sync; + float x_syncincr; + int x_isrunning; /* to know if sync should be 0.0 or 1.0 */ + t_clock *x_clock; +} t_record; + +static t_class *record_class; + +static void record_tick(t_record *x) +{ + arsic_redraw((t_arsic *)x); +} + +static void record_setsync(t_record *x) +{ + /* CHECKED: clipped to array size -- using indices, not points */ + float range = (float)(x->x_endindex - x->x_startindex); + int phase = x->x_phase; + if (phase == SHARED_INT_MAX || range < 1.0) + { + x->x_sync = (x->x_isrunning ? 1.0 : 0); /* CHECKED */ + x->x_syncincr = 0; + } + else + { + x->x_sync = (float)(phase - x->x_startindex) / range; + x->x_syncincr = 1.0 / range; + } +} + +static void record_mstoindex(t_record *x) +{ + t_arsic *sic = (t_arsic *)x; + x->x_startindex = (int)(x->x_startpoint * sic->s_ksr); + if (x->x_startindex < 0) + x->x_startindex = 0; /* CHECKED */ + x->x_endindex = (int)(x->x_endpoint * sic->s_ksr); + if (x->x_endindex > sic->s_vecsize + || x->x_endindex <= 0) + x->x_endindex = sic->s_vecsize; /* CHECKED (both ways) */ + record_setsync(x); +} + +static void record_set(t_record *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); + record_mstoindex(x); +} + +static void record_startpoint(t_record *x, t_floatarg f) +{ + x->x_startpoint = f; + record_mstoindex(x); +} + +static void record_endpoint(t_record *x, t_floatarg f) +{ + x->x_endpoint = f; + record_mstoindex(x); +} + +static void record_float(t_record *x, t_float f) +{ + if (x->x_isrunning = (f != 0)) + { + /* CHECKED: no (re)start in append mode */ + /* LATER consider restart if x->x_pauseindex == SHARED_INT_MAX */ + x->x_phase = x->x_appendmode ? x->x_pauseindex : x->x_startindex; + if (x->x_phase >= x->x_endindex) x->x_phase = SHARED_INT_MAX; + } + else if (x->x_phase != SHARED_INT_MAX) /* CHECKED: no rewind */ + { + record_tick(x); + x->x_pauseindex = x->x_phase; + x->x_phase = SHARED_INT_MAX; + } + record_setsync(x); +} + +static void record_append(t_record *x, t_floatarg f) +{ + if (f != 0) + { + x->x_appendmode = 1; /* CHECKED: always allow appending */ + } + else x->x_appendmode = 0; +} + +static void record_loop(t_record *x, t_floatarg f) +{ + x->x_loopmode = (f != 0); +} + +static t_int *record_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + int nch = sic->s_nchannels; + t_float *out = (t_float *)(w[3 + nch]); + t_record *x = (t_record *)sic; + int phase = x->x_phase; + int endphase = x->x_endindex; + float sync = x->x_sync; + if (sic->s_playable && endphase > phase) + { + int vecsize = sic->s_vecsize; + float syncincr = x->x_syncincr; + int ch, over, i, nxfer; +loopover: + if ((nxfer = endphase - phase) > nblock) + { + nxfer = nblock; + over = 0; + } + else over = 1; + ch = nch; + while (ch--) + { + t_float *vp = sic->s_vectors[ch]; + if (vp) + { + t_float *ip = (t_float *)(w[3 + ch]); + vp += phase; + i = nxfer; + /* LATER consider handling under and overflows */ + while (i--) *vp++ = *ip++; + } + } + i = nxfer; + while (i--) + { + *out++ = sync; + sync += syncincr; + } + if (over) + { + nblock -= nxfer; + if (x->x_loopmode + && (phase = x->x_startindex) < endphase) + { + x->x_phase = phase; + x->x_sync = sync = 0; + if (nblock > 0) goto loopover; + goto done; + } + clock_delay(x->x_clock, 0); + /* CHECKED: no restart in append mode */ + x->x_pauseindex = SHARED_INT_MAX; + x->x_phase = SHARED_INT_MAX; + x->x_sync = 1.0; + x->x_syncincr = 0; + } + else + { + x->x_phase += nxfer; + x->x_sync = sync; + goto done; + } + } + while (nblock--) *out++ = sync; +done: + return (w + sic->s_nperfargs + 1); +} + +static void record_dsp(t_record *x, t_signal **sp) +{ + arsic_dsp((t_arsic *)x, sp, record_perform, 1); + record_mstoindex(x); +} + +static void record_free(t_record *x) +{ + arsic_free((t_arsic *)x); + if (x->x_clock) clock_free(x->x_clock); +} + +static void *record_new(t_symbol *s, t_floatarg f) +{ + /* one auxiliary signal: sync output */ + t_record *x = (t_record *)arsic_new(record_class, s, (int)f, 0, 1); + if (x) + { + int nch = arsic_getnchannels((t_arsic *)x); + arsic_setminsize((t_arsic *)x, 2); + x->x_startpoint = 0; + x->x_endpoint = 0; + x->x_appendmode = 0; + x->x_loopmode = 0; + x->x_pauseindex = SHARED_INT_MAX; + x->x_phase = SHARED_INT_MAX; + x->x_isrunning = 0; + record_mstoindex(x); + x->x_clock = clock_new(x, (t_method)record_tick); + while (--nch) + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-2")); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft-1")); + outlet_new((t_object *)x, &s_signal); + } + return (x); +} + +void record_tilde_setup(void) +{ + record_class = class_new(gensym("record~"), + (t_newmethod)record_new, + (t_method)record_free, + sizeof(t_record), 0, + A_DEFSYM, A_DEFFLOAT, 0); + arsic_setup(record_class, record_dsp, record_float); + class_addmethod(record_class, (t_method)record_startpoint, + gensym("ft-2"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_endpoint, + gensym("ft-1"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_append, + gensym("append"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_loop, + gensym("loop"), A_FLOAT, 0); + class_addmethod(record_class, (t_method)record_set, + gensym("set"), A_SYMBOL, 0); +} diff --git a/cyclone/sickle/sah.c b/cyclone/sickle/sah.c new file mode 100644 index 0000000..afac1e0 --- /dev/null +++ b/cyclone/sickle/sah.c @@ -0,0 +1,70 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _sah +{ + t_sic x_sic; + t_float x_threshold; + t_float x_lastin; + t_float x_lastout; +} t_sah; + +static t_class *sah_class; + +static t_int *sah_perform(t_int *w) +{ + t_sah *x = (t_sah *)(w[1]); + int nblock = (t_int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + t_float threshold = x->x_threshold; + t_float lastin = x->x_lastin; + t_float lastout = x->x_lastout; + while (nblock--) + { + float f = *in2++; + if (lastin <= threshold && f > threshold) /* CHECKME <=, > */ + lastout = *in1; + in1++; + lastin = f; + *out++ = lastout; + } + x->x_lastin = lastin; + x->x_lastout = lastout; + return (w + 6); +} + +static void sah_dsp(t_sah *x, t_signal **sp) +{ + dsp_add(sah_perform, 5, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void sah_float(t_sah *x, t_float f) +{ + x->x_threshold = f; +} + +static void *sah_new(t_floatarg f) +{ + t_sah *x = (t_sah *)pd_new(sah_class); + x->x_threshold = f; + x->x_lastin = 0; + x->x_lastout = 0; + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void sah_tilde_setup(void) +{ + sah_class = class_new(gensym("sah~"), + (t_newmethod)sah_new, 0, + sizeof(t_sah), 0, A_DEFFLOAT, 0); + sic_setup(sah_class, sah_dsp, sah_float); +} diff --git a/cyclone/sickle/sickle.c b/cyclone/sickle/sickle.c new file mode 100644 index 0000000..765209a --- /dev/null +++ b/cyclone/sickle/sickle.c @@ -0,0 +1,93 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include "m_pd.h" +#include "unstable/fragile.h" +#include "common/loud.h" +#include "common/port.h" +#include "hammer/file.h" +#include "../build_counter" +void allsickles_setup(void); + +typedef struct _sickle +{ + t_object x_ob; + t_symbol *x_dir; + t_hammerfile *x_filehandle; +} t_sickle; + +static t_class *sickle_class; +static int sickle_firstndx; +static int sickle_lastndx; + +static void sickle_readhook(t_pd *z, t_symbol *fn, int ac, t_atom *av) +{ + import_max(fn->s_name, ""); +} + +static void sickle_import(t_sickle *x, t_symbol *fn, t_symbol *dir) +{ + if (fn && fn != &s_) + { + if (!dir || dir == &s_) dir = x->x_dir; + import_max(fn->s_name, (dir && dir != &s_) ? dir->s_name : ""); + } + else + hammerpanel_open(x->x_filehandle); +} + +static void sickle_click(t_sickle *x, t_floatarg xpos, t_floatarg ypos, + t_floatarg shift, t_floatarg ctrl, t_floatarg alt) +{ + sickle_import(x, 0, 0); +} + +static void sickle_bang(t_sickle *x) +{ + fragile_class_printnames("sickle classes are: ", + sickle_firstndx, sickle_lastndx); +} + +static void sickle_free(t_sickle *x) +{ + hammerfile_free(x->x_filehandle); +} + +static void *sickle_new(t_symbol *s) +{ + t_sickle *x = (t_sickle *)pd_new(sickle_class); + x->x_filehandle = hammerfile_new((t_pd *)x, 0, sickle_readhook, 0, 0); + x->x_dir = (s && s != &s_ ? s : canvas_getdir(x->x_filehandle->f_canvas)); + return (x); +} + +void sickle_setup(void) +{ + if (canvas_getcurrent()) + { + /* Loading the library by object creation is banned, because of a danger + of having some of the classes already loaded. LATER rethink. */ + loud_error(0, "apparently an attempt to create a 'sickle' object"); + loud_errand(0, "without having sickle library preloaded"); + return; + } + if (!zgetfn(&pd_objectmaker, gensym("cyclone"))) + post("this is sickle %s, %s %s build", + CYCLONE_VERSION, loud_ordinal(CYCLONE_BUILD), CYCLONE_RELEASE); + sickle_class = class_new(gensym("sickle"), + (t_newmethod)sickle_new, + (t_method)sickle_free, + sizeof(t_sickle), 0, A_DEFSYM, 0); + class_addbang(sickle_class, sickle_bang); + class_addmethod(sickle_class, (t_method)sickle_import, + gensym("import"), A_DEFSYM, A_DEFSYM, 0); + class_addmethod(sickle_class, (t_method)sickle_click, + gensym("click"), + A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, A_FLOAT, 0); + hammerfile_setup(sickle_class, 0); + sickle_firstndx = fragile_class_count(); + allsickles_setup(); + sickle_lastndx = fragile_class_count() - 1; +} diff --git a/cyclone/sickle/sinh.c b/cyclone/sickle/sinh.c new file mode 100644 index 0000000..523c28a --- /dev/null +++ b/cyclone/sickle/sinh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sinhf sinh +#endif + +typedef t_sic t_sinh; +static t_class *sinh_class; + +static t_int *sinh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = sinhf(f); /* CHECKME no protection against overflow */ + } + return (w + 4); +} + +static void sinh_dsp(t_sinh *x, t_signal **sp) +{ + dsp_add(sinh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *sinh_new(void) +{ + t_sinh *x = (t_sinh *)pd_new(sinh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void sinh_tilde_setup(void) +{ + sinh_class = class_new(gensym("sinh~"), + (t_newmethod)sinh_new, 0, + sizeof(t_sinh), 0, 0); + sic_setup(sinh_class, sinh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/sinx.c b/cyclone/sickle/sinx.c new file mode 100644 index 0000000..b303024 --- /dev/null +++ b/cyclone/sickle/sinx.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* by definition, this is just an interface to the -lm call + (do not use costable) */ + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define sinf sin +#endif + +typedef t_sic t_sinx; +static t_class *sinx_class; + +static t_int *sinx_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = sinf(f); + } + return (w + 4); +} + +static void sinx_dsp(t_sinx *x, t_signal **sp) +{ + dsp_add(sinx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *sinx_new(void) +{ + t_sinx *x = (t_sinx *)pd_new(sinx_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void sinx_tilde_setup(void) +{ + sinx_class = class_new(gensym("sinx~"), + (t_newmethod)sinx_new, 0, + sizeof(t_sinx), 0, 0); + sic_setup(sinx_class, sinx_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/slide.c b/cyclone/sickle/slide.c new file mode 100644 index 0000000..92001b2 --- /dev/null +++ b/cyclone/sickle/slide.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define SLIDE_DEFUP 1. +#define SLIDE_DEFDN 1. + +typedef struct _slide +{ + t_sic x_sic; + t_float x_last; +} t_slide; + +static t_class *slide_class; + +static t_int *slide_perform(t_int *w) +{ + t_slide *x = (t_slide *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *in3 = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + t_float last = x->x_last; + while (nblock--) + { + float f = *in1++; + if (f > last) + { + float up = *in2++; + if (up > 1.) /* CHECKED */ + last += (f - last) / up; + else + last = f; + in3++; + } + else if (f < last) + { + float dn = *in3++; + if (dn > 1.) /* CHECKED */ + last += (f - last) / dn; + else + last = f; + in2++; + } + *out++ = last; + } + x->x_last = last; + return (w + 7); +} + +static void slide_dsp(t_slide *x, t_signal **sp) +{ + dsp_add(slide_perform, 6, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void *slide_new(t_symbol *s, int ac, t_atom *av) +{ + t_slide *x = (t_slide *)pd_new(slide_class); + sic_inlet((t_sic *)x, 1, SLIDE_DEFUP, 0, ac, av); + sic_inlet((t_sic *)x, 2, SLIDE_DEFDN, 1, ac, av); + outlet_new((t_object *)x, &s_signal); + x->x_last = 0; + return (x); +} + +void slide_tilde_setup(void) +{ + slide_class = class_new(gensym("slide~"), + (t_newmethod)slide_new, 0, + sizeof(t_slide), 0, A_GIMME, 0); + sic_setup(slide_class, slide_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/spike.c b/cyclone/sickle/spike.c new file mode 100644 index 0000000..13f9361 --- /dev/null +++ b/cyclone/sickle/spike.c @@ -0,0 +1,109 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +typedef struct _spike +{ + t_sic x_sic; + t_float x_last; + int x_count; + int x_precount; + int x_nwait; + float x_waittime; + float x_ksr; + float x_rcpksr; + t_clock *x_clock; +} t_spike; + +static t_class *spike_class; + +static void spike_tick(t_spike *x) +{ + outlet_float(((t_object *)x)->ob_outlet, x->x_count * x->x_rcpksr); + x->x_count = x->x_precount; +} + +static void spike_ft1(t_spike *x, t_floatarg f) +{ + if ((x->x_waittime = f) < 0.) + x->x_waittime = 0.; + x->x_nwait = (int)(x->x_waittime * x->x_ksr); +} + +static t_int *spike_perform(t_int *w) +{ + t_spike *x = (t_spike *)(w[1]); + int nblock = (int)(w[2]); + t_float *in = (t_float *)(w[3]); + t_float last = x->x_last; + int count = x->x_count; + int nwait = x->x_nwait; + if (count + nblock > nwait) + { + /* LATER efficiency tricks */ + while (nblock--) + { + float f = *in++; + if (last == 0. && f != 0. /* CHECKED zero-to-nonzero */ + && count /* CHECKED no firing at startup */ + && count >= nwait) + { + clock_delay(x->x_clock, 0); + x->x_last = in[nblock - 1]; + x->x_count = count; + x->x_precount = nblock; + return (w + 4); + } + count++; + last = f; + } + x->x_last = last; + x->x_count = count; + } + else + { + x->x_last = in[nblock - 1]; + x->x_count += nblock; + } + return (w + 4); +} + +static void spike_dsp(t_spike *x, t_signal **sp) +{ + x->x_ksr = sp[0]->s_sr * 0.001; + x->x_rcpksr = 1000.0 / sp[0]->s_sr; + x->x_nwait = (int)(x->x_waittime * x->x_ksr); + dsp_add(spike_perform, 3, x, sp[0]->s_n, sp[0]->s_vec); +} + +static void spike_free(t_spike *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *spike_new(t_floatarg f) +{ + t_spike *x = (t_spike *)pd_new(spike_class); + x->x_last = 0.; + x->x_ksr = sys_getsr() * 0.001; + spike_ft1(x, f); + inlet_new((t_object *)x, (t_pd *)x, &s_float, gensym("ft1")); + outlet_new((t_object *)x, &s_float); + x->x_clock = clock_new(x, (t_method)spike_tick); + return (x); +} + +void spike_tilde_setup(void) +{ + spike_class = class_new(gensym("spike~"), + (t_newmethod)spike_new, + (t_method)spike_free, + sizeof(t_spike), 0, + A_DEFFLOAT, 0); + sic_setup(spike_class, spike_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(spike_class, (t_method)spike_ft1, + gensym("ft1"), A_FLOAT, 0); +} diff --git a/cyclone/sickle/tanh.c b/cyclone/sickle/tanh.c new file mode 100644 index 0000000..7473dcf --- /dev/null +++ b/cyclone/sickle/tanh.c @@ -0,0 +1,48 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define tanhf tanh +#endif + +typedef t_sic t_tanh; +static t_class *tanh_class; + +static t_int *tanh_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = tanhf(f); /* CHECKME no protection against overflow */ + } + return (w + 4); +} + +static void tanh_dsp(t_tanh *x, t_signal **sp) +{ + dsp_add(tanh_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *tanh_new(void) +{ + t_tanh *x = (t_tanh *)pd_new(tanh_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void tanh_tilde_setup(void) +{ + tanh_class = class_new(gensym("tanh~"), + (t_newmethod)tanh_new, 0, + sizeof(t_tanh), 0, 0); + sic_setup(tanh_class, tanh_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/tanx.c b/cyclone/sickle/tanx.c new file mode 100644 index 0000000..d2a1102 --- /dev/null +++ b/cyclone/sickle/tanx.c @@ -0,0 +1,51 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <math.h> +#include "m_pd.h" +#include "sickle/sic.h" + +/* by definition, this is just an interface to the -lm call + (do not use costable) */ + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define tanf tan +#endif + +typedef t_sic t_tanx; +static t_class *tanx_class; + +static t_int *tanx_perform(t_int *w) +{ + int nblock = (int)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + while (nblock--) + { + float f = *in++; + *out++ = tanf(f); + } + return (w + 4); +} + +static void tanx_dsp(t_tanx *x, t_signal **sp) +{ + dsp_add(tanx_perform, 3, sp[0]->s_n, sp[0]->s_vec, sp[1]->s_vec); +} + +static void *tanx_new(void) +{ + t_tanx *x = (t_tanx *)pd_new(tanx_class); + outlet_new((t_object *)x, &s_signal); + return (x); +} + +void tanx_tilde_setup(void) +{ + tanx_class = class_new(gensym("tanx~"), + (t_newmethod)tanx_new, 0, + sizeof(t_tanx), 0, 0); + sic_setup(tanx_class, tanx_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/train.c b/cyclone/sickle/train.c new file mode 100644 index 0000000..b07ba9a --- /dev/null +++ b/cyclone/sickle/train.c @@ -0,0 +1,117 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "shared.h" +#include "sickle/sic.h" + +#define TRAIN_DEFPERIOD 1000 +#define TRAIN_DEFWIDTH 0.5 +#define TRAIN_DEFOFFSET 0 + +typedef struct _train +{ + t_sic x_sic; + int x_on; + double x_phase; + float x_rcpksr; + t_outlet *x_bangout; + t_clock *x_clock; +} t_train; + +static t_class *train_class; + +static void train_tick(t_train *x) +{ + outlet_bang(x->x_bangout); +} + +static t_int *train_perform(t_int *w) +{ + t_train *x = (t_train *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *in3 = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + float rcpksr = x->x_rcpksr; + double ph = x->x_phase; + double tfph = ph + SHARED_UNITBIT32; + t_shared_wrappy wrappy; + int32 normhipart; + int on = x->x_on; + int edge = 0; + + wrappy.w_d = SHARED_UNITBIT32; + normhipart = wrappy.w_i[SHARED_HIOFFSET]; + + while (nblock--) + { + double onph, offph; + float period = *in1++; + + wrappy.w_d = *in3++ + SHARED_UNITBIT32; + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + onph = wrappy.w_d - SHARED_UNITBIT32; + + wrappy.w_d = onph + *in2++ + SHARED_UNITBIT32; + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + offph = wrappy.w_d - SHARED_UNITBIT32; + + if (offph > onph ? ph < offph && ph >= onph : ph < offph || ph >= onph) + { + if (!on) on = edge = 1; + *out++ = 1.; + } + else + { + on = 0; + *out++ = 0.; + } + if (period > rcpksr) /* LATER rethink */ + tfph += rcpksr / period; /* LATER revisit (profiling?) */ + wrappy.w_d = tfph; + wrappy.w_i[SHARED_HIOFFSET] = normhipart; + ph = wrappy.w_d - SHARED_UNITBIT32; + } + x->x_phase = ph; + x->x_on = on; + if (edge) clock_delay(x->x_clock, 0); + return (w + 7); +} + +static void train_dsp(t_train *x, t_signal **sp) +{ + x->x_rcpksr = 1000. / sp[0]->s_sr; + dsp_add(train_perform, 6, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void train_free(t_train *x) +{ + if (x->x_clock) clock_free(x->x_clock); +} + +static void *train_new(t_symbol *s, int ac, t_atom *av) +{ + t_train *x = (t_train *)pd_new(train_class); + x->x_on = 0; + x->x_phase = 0; + sic_inlet((t_sic *)x, 0, TRAIN_DEFPERIOD, 0, ac, av); + sic_inlet((t_sic *)x, 1, TRAIN_DEFWIDTH, 1, ac, av); + sic_inlet((t_sic *)x, 2, TRAIN_DEFOFFSET, 2, ac, av); + outlet_new((t_object *)x, &s_signal); + x->x_bangout = outlet_new((t_object *)x, &s_bang); + x->x_clock = clock_new(x, (t_method)train_tick); + return (x); +} + +void train_tilde_setup(void) +{ + train_class = class_new(gensym("train~"), + (t_newmethod)train_new, + (t_method)train_free, + sizeof(t_train), 0, A_GIMME, 0); + sic_setup(train_class, train_dsp, SIC_FLOATTOSIGNAL); +} diff --git a/cyclone/sickle/trapezoid.c b/cyclone/sickle/trapezoid.c new file mode 100644 index 0000000..b33cb02 --- /dev/null +++ b/cyclone/sickle/trapezoid.c @@ -0,0 +1,105 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define TRAPEZOID_DEFUP 0.1 /* a bug? */ +#define TRAPEZOID_DEFDN 0.9 /* a bug? */ +#define TRAPEZOID_DEFLO 0.0 +#define TRAPEZOID_DEFHI 1.0 + +typedef struct _trapezoid +{ + t_sic x_sic; + float x_low; + float x_range; +} t_trapezoid; + +static t_class *trapezoid_class; + +static void trapezoid_lo(t_trapezoid *x, t_floatarg f) +{ + float high = x->x_low + x->x_range; + x->x_low = f; + x->x_range = high - x->x_low; +} + +static void trapezoid_hi(t_trapezoid *x, t_floatarg f) +{ + x->x_range = f - x->x_low; +} + +/* LATER optimize */ +static t_int *trapezoid_perform(t_int *w) +{ + t_trapezoid *x = (t_trapezoid *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *in3 = (t_float *)(w[5]); + t_float *out = (t_float *)(w[6]); + float low = x->x_low; + float range = x->x_range; + while (nblock--) + { + float ph = *in1++; + float upph = *in2++; + float dnph = *in3++; + /* CHECKED ph wrapped */ + if (ph < 0.) + ph -= (int)ph - 1.; + else if (ph > 1.) + ph -= (int)ph; + /* CHECKED upph, dnph clipped */ + if (upph < 0.) + upph = 0.; + else if (upph > 1.) /* CHECKME */ + upph = 1.; + if (dnph < upph) + dnph = upph; + else if (dnph > 1.) + dnph = 1.; + + if (ph < upph) + ph /= upph; + else if (ph < dnph) + ph = 1.; + else if (dnph < 1.) + ph = (1. - ph) / (1. - dnph); + else + ph = 0.; + *out++ = low + ph * range; + } + return (w + 7); +} + +static void trapezoid_dsp(t_trapezoid *x, t_signal **sp) +{ + dsp_add(trapezoid_perform, 6, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void *trapezoid_new(t_symbol *s, int ac, t_atom *av) +{ + t_trapezoid *x = (t_trapezoid *)pd_new(trapezoid_class); + sic_inlet((t_sic *)x, 1, TRAPEZOID_DEFUP, 0, ac, av); + sic_inlet((t_sic *)x, 2, TRAPEZOID_DEFDN, 1, ac, av); + outlet_new((t_object *)x, &s_signal); + x->x_low = TRAPEZOID_DEFLO; + x->x_range = (TRAPEZOID_DEFHI - TRAPEZOID_DEFLO); + return (x); +} + +void trapezoid_tilde_setup(void) +{ + trapezoid_class = class_new(gensym("trapezoid~"), + (t_newmethod)trapezoid_new, 0, + sizeof(t_trapezoid), 0, A_GIMME, 0); + sic_setup(trapezoid_class, trapezoid_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(trapezoid_class, (t_method)trapezoid_lo, + gensym("lo"), A_DEFFLOAT, 0); /* CHECKME */ + class_addmethod(trapezoid_class, (t_method)trapezoid_hi, + gensym("hi"), A_DEFFLOAT, 0); /* CHECKME */ +} diff --git a/cyclone/sickle/triangle.c b/cyclone/sickle/triangle.c new file mode 100644 index 0000000..703e5ba --- /dev/null +++ b/cyclone/sickle/triangle.c @@ -0,0 +1,95 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define TRIANGLE_DEFPHASE 0.5 +#define TRIANGLE_DEFLO -1.0 +#define TRIANGLE_DEFHI 1.0 + +typedef struct _triangle +{ + t_sic x_sic; + float x_low; + float x_range; +} t_triangle; + +static t_class *triangle_class; + +static void triangle_lo(t_triangle *x, t_floatarg f) +{ + float high = x->x_low + x->x_range; + x->x_low = f; + x->x_range = high - x->x_low; +} + +static void triangle_hi(t_triangle *x, t_floatarg f) +{ + x->x_range = f - x->x_low; +} + +/* LATER optimize */ +static t_int *triangle_perform(t_int *w) +{ + t_triangle *x = (t_triangle *)(w[1]); + int nblock = (int)(w[2]); + t_float *in1 = (t_float *)(w[3]); + t_float *in2 = (t_float *)(w[4]); + t_float *out = (t_float *)(w[5]); + float low = x->x_low; + float range = x->x_range; + while (nblock--) + { + float ph = *in1++; + float peakph = *in2++; + /* CHECKED ph wrapped */ + if (ph < 0.) + ph -= (int)ph - 1.; + else if (ph > 1.) + ph -= (int)ph; + /* CHECKED peakph clipped */ + if (peakph < 0.) + peakph = 0.; + else if (peakph > 1.) + peakph = 1.; + + if (ph < peakph) + ph /= peakph; + else if (peakph < 1.) + ph = (1. - ph) / (1. - peakph); + else + ph = 0.; + *out++ = low + ph * range; + } + return (w + 6); +} + +static void triangle_dsp(t_triangle *x, t_signal **sp) +{ + dsp_add(triangle_perform, 5, x, sp[0]->s_n, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec); +} + +static void *triangle_new(t_symbol *s, int ac, t_atom *av) +{ + t_triangle *x = (t_triangle *)pd_new(triangle_class); + sic_inlet((t_sic *)x, 1, TRIANGLE_DEFPHASE, 0, ac, av); + outlet_new((t_object *)x, &s_signal); + x->x_low = TRIANGLE_DEFLO; + x->x_range = (TRIANGLE_DEFHI - TRIANGLE_DEFLO); + return (x); +} + +void triangle_tilde_setup(void) +{ + triangle_class = class_new(gensym("triangle~"), + (t_newmethod)triangle_new, 0, + sizeof(t_triangle), 0, A_GIMME, 0); + sic_setup(triangle_class, triangle_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(triangle_class, (t_method)triangle_lo, + gensym("lo"), A_DEFFLOAT, 0); /* CHECKED */ + class_addmethod(triangle_class, (t_method)triangle_hi, + gensym("hi"), A_DEFFLOAT, 0); /* CHECKED */ +} diff --git a/cyclone/sickle/vectral.c b/cyclone/sickle/vectral.c new file mode 100644 index 0000000..b9cdf69 --- /dev/null +++ b/cyclone/sickle/vectral.c @@ -0,0 +1,235 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "sickle/sic.h" + +#define VECTRAL_DEFSIZE 512 + +struct _vectral; +typedef void (*t_vectral_perform)(struct _vectral *, int, + t_float *, t_float *, t_float *, t_float *); + +typedef struct _vectral +{ + t_sic x_sic; + t_vectral_perform x_perform; + int x_bufsize; + t_float *x_buffer; + t_float *x_lastframe; + /* rampsmooth and slide state */ + double x_upcoef; + double x_downcoef; + /* deltaclip state */ + float x_lo; + float x_hi; +} t_vectral; + +static t_class *vectral_class; + +/* LATER after any modification make sure about syncing other variants + of perform routine to the bypassing version */ +/* this is: for i in [0..nblock) buf[in2[i]] = in3[i], out[i] = buf[in1[i]] */ +static void vectral_perform_bypass(t_vectral *x, int nblock, + t_float *in1, t_float *in2, t_float *in3, + t_float *out) +{ + t_float *buf = x->x_buffer; + int bufsize = x->x_bufsize; + t_float *last = x->x_lastframe; + int blocksize = nblock; + while (nblock--) + { + int indx = (int)*in2++; + /* CHECKED buffer not zeroed out (the buffer's garbage remains) */ + if (indx >= 0 && indx < bufsize) + buf[indx] = *in3; + in3++; + } + while (blocksize--) + { + int ondx = (int)*in1++; + if (ondx >= 0 && ondx < bufsize) + *out++ = *last++ = buf[ondx]; + else + /* CHECKED garbage in the output vector is cleared */ + *out++ = *last++ = 0.; + } +} + +/* this one is used for rampsmooth mode as well (see rampsmooth.c) + LATER recheck */ +static void vectral_perform_slide(t_vectral *x, int nblock, + t_float *in1, t_float *in2, t_float *in3, + t_float *out) +{ + t_float *buf = x->x_buffer; + int bufsize = x->x_bufsize; + double upcoef = x->x_upcoef; + double downcoef = x->x_downcoef; + t_float *last = x->x_lastframe; + int blocksize = nblock; + while (nblock--) + { + int indx = (int)*in2++; + if (indx >= 0 && indx < bufsize) + buf[indx] = *in3; + in3++; + } + while (blocksize--) + { + int ondx = (int)*in1++; + if (ondx >= 0 && ondx < bufsize) + { + /* CHECKME what is smoothed, and FIXME */ + float delta = buf[ondx] - *last; + *out++ = + (*last++ += (delta > 0 ? delta * upcoef : delta * downcoef)); + } + else *out++ = *last++ = 0.; + } +} + +static void vectral_perform_clip(t_vectral *x, int nblock, + t_float *in1, t_float *in2, t_float *in3, + t_float *out) +{ + t_float *buf = x->x_buffer; + int bufsize = x->x_bufsize; + float lo = x->x_lo; + float hi = x->x_hi; + t_float *last = x->x_lastframe; + int blocksize = nblock; + while (nblock--) + { + int indx = (int)*in2++; + if (indx >= 0 && indx < bufsize) + buf[indx] = *in3; + in3++; + } + while (blocksize--) + { + int ondx = (int)*in1++; + if (ondx >= 0 && ondx < bufsize) + { + /* CHECKME what is smoothed, and FIXME */ + float delta = buf[ondx] - *last; + if (delta < lo) + *out++ = (*last++ += lo); + else if (delta > hi) + *out++ = (*last++ += hi); + else + *out++ = *last++ = buf[ondx]; + } + else *out++ = *last++ = 0.; + } +} + +static t_int *vectral_perform(t_int *w) +{ + t_vectral *x = (t_vectral *)(w[1]); + (*x->x_perform)(x, (int)(w[2]), (t_float *)(w[3]), (t_float *)(w[4]), + (t_float *)(w[5]), (t_float *)(w[6])); + return (w + 7); +} + +static void vectral_dsp(t_vectral *x, t_signal **sp) +{ + int nblock = sp[0]->s_n; + if (nblock > x->x_bufsize) + nblock = x->x_bufsize; /* CHECKME */ + dsp_add(vectral_perform, 6, x, nblock, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec); +} + +static void vectral_rampsmooth(t_vectral *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_FLOAT) + { + int i; + x->x_upcoef = ((i = (int)av->a_w.w_float) > 1 ? 1. / (double)i : 1.); + ac--; av++; + if (ac && av->a_type == A_FLOAT) + x->x_downcoef = + ((i = (int)av->a_w.w_float) > 1 ? 1. / (double)i : 1.); + else + x->x_downcoef = 1.; /* CHECKED */ + x->x_perform = vectral_perform_slide; /* see above */ + } + else x->x_perform = vectral_perform_bypass; /* CHECKED */ +} + +static void vectral_slide(t_vectral *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_FLOAT) + { + double d; + x->x_upcoef = ((d = av->a_w.w_float) > 1. ? 1. / d : 1.); + ac--; av++; + if (ac && av->a_type == A_FLOAT) + x->x_downcoef = ((d = av->a_w.w_float) > 1. ? 1. / d : 1.); + else + x->x_downcoef = 1.; /* CHECKED */ + x->x_perform = vectral_perform_slide; + } + else x->x_perform = vectral_perform_bypass; /* CHECKED */ +} + +/* CHECKED 'deltaclip <hi> <lo>' (deltaclip~'s args are swapped) */ +static void vectral_deltaclip(t_vectral *x, t_symbol *s, int ac, t_atom *av) +{ + if (ac && av->a_type == A_FLOAT) + { + x->x_hi = av->a_w.w_float; + ac--; av++; + if (ac && av->a_type == A_FLOAT) + x->x_lo = av->a_w.w_float; + else + x->x_lo = 0.; /* CHECKED */ + } + else x->x_lo = x->x_hi = 0.; /* CHECKED */ + x->x_perform = vectral_perform_clip; +} + +static void vectral_free(t_vectral *x) +{ + if (x->x_buffer) + freebytes(x->x_buffer, x->x_bufsize * sizeof(*x->x_buffer)); + if (x->x_lastframe) + freebytes(x->x_lastframe, x->x_bufsize * sizeof(*x->x_lastframe)); +} + +static void *vectral_new(t_floatarg f) +{ + t_vectral *x = (t_vectral *)pd_new(vectral_class); + int i = (int)f; + x->x_bufsize = (i > 0 ? i : VECTRAL_DEFSIZE); + if (!(x->x_buffer = getbytes(x->x_bufsize * sizeof(*x->x_buffer)))) + goto failure; + if (!(x->x_lastframe = getbytes(x->x_bufsize * sizeof(*x->x_lastframe)))) + goto failure; + x->x_perform = vectral_perform_bypass; + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + outlet_new((t_object *)x, &s_signal); + return (x); +failure: + pd_free((t_pd *)x); + return (0); +} + +void vectral_tilde_setup(void) +{ + vectral_class = class_new(gensym("vectral~"), + (t_newmethod)vectral_new, + (t_method)vectral_free, + sizeof(t_vectral), 0, A_DEFFLOAT, 0); + sic_setup(vectral_class, vectral_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(vectral_class, (t_method)vectral_rampsmooth, + gensym("rampsmooth"), A_GIMME, 0); + class_addmethod(vectral_class, (t_method)vectral_slide, + gensym("slide"), A_GIMME, 0); + class_addmethod(vectral_class, (t_method)vectral_deltaclip, + gensym("deltaclip"), A_GIMME, 0); +} diff --git a/cyclone/sickle/wave.c b/cyclone/sickle/wave.c new file mode 100644 index 0000000..7804c88 --- /dev/null +++ b/cyclone/sickle/wave.c @@ -0,0 +1,161 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +/* CHECKME (the refman): the extra channels are not played */ + +typedef struct _wave +{ + t_arsic x_arsic; + int x_nointerp; +} t_wave; + +static t_class *wave_class; + +static void wave_interp(t_wave *x, t_floatarg f) +{ + x->x_nointerp = (f == 0); + arsic_setminsize((t_arsic *)x, (x->x_nointerp ? 1 : 4)); + arsic_check((t_arsic *)x); +} + +static void wave_set(t_wave *x, t_symbol *s) +{ + arsic_setarray((t_arsic *)x, s, 1); +} + +static t_int *wave_perform(t_int *w) +{ + t_arsic *sic = (t_arsic *)(w[1]); + int nblock = (int)(w[2]); + int nch = sic->s_nchannels; + t_int *outp = w + 6; + if (sic->s_playable) + { + t_wave *x = (t_wave *)sic; + t_float *xin = (t_float *)(w[3]); + t_float *sin = (t_float *)(w[4]); + t_float *ein = (t_float *)(w[5]); + int vecsize = sic->s_vecsize; + t_float **vectable = sic->s_vectors; + float ksr = sic->s_ksr; + int nointerp = x->x_nointerp; + int maxindex = (nointerp ? vecsize - 1 : vecsize - 3); + int iblock; + + for (iblock = 0; iblock < nblock; iblock++) + { + float spos = *sin++ * ksr; + float xpos = *ein++ * ksr; + /* msp seems to be buggy here, but CHECKME again */ + int siz = (int)((xpos > 0 ? xpos : maxindex) - spos); + float phase = *xin++; + int ndx; + int ch = nch; + /* CHECKED: phase is clipped, not wrapped */ + if (phase < 0) phase = 0; + else if (phase > 1.0) phase = 1.0; + xpos = (siz > 0 ? spos + siz * phase : spos); + ndx = (int)xpos; + if (nointerp) + { + if (ndx < 0) ndx = 0; + else if (ndx > maxindex) ndx = maxindex; + while (ch--) + { + t_float *vp = vectable[ch]; + t_float *out = (t_float *)(outp[ch]); + out[iblock] = (vp ? vp[ndx] : 0); + } + } + else + { + float frac, a, b, c, d, cminusb; + if (ndx < 1) + ndx = 1, frac = 0; + else if (ndx > maxindex) + ndx = maxindex, frac = 1; + else frac = xpos - ndx; + while (ch--) + { + t_float *vp = vectable[ch]; + t_float *out = (t_float *)(outp[ch]); + if (vp) + { + vp += ndx; + a = vp[-1]; + b = vp[0]; + c = vp[1]; + d = vp[2]; + cminusb = c-b; + out[iblock] = b + frac * ( + cminusb - 0.1666667f * (1. - frac) * ( + (d - a - 3.0f * cminusb) * frac + + (d + 2.0f * a - 3.0f * b) + ) + ); + } + else out[iblock] = 0; + } + } + } + } + else + { + int ch = nch; + while (ch--) + { + t_float *out = (t_float *)outp[ch]; + int n = nblock; + while (n--) *out++ = 0; + } + } + return (w + sic->s_nperfargs + 1); +} + +static void wave_dsp(t_wave *x, t_signal **sp) +{ + arsic_dsp((t_arsic *)x, sp, wave_perform, 1); +} + +static void wave_free(t_wave *x) +{ + arsic_free((t_arsic *)x); +} + +static void *wave_new(t_symbol *s, t_floatarg f1, t_floatarg f2, t_floatarg f3) +{ + /* three auxiliary signals: phase, clipstart, and clipend inputs */ + t_wave *x = (t_wave *)arsic_new(wave_class, s, (int)f3, 0, 3); + if (x) + { + int nch = arsic_getnchannels((t_arsic *)x); + if (f1 < 0) f1 = 0; + if (f2 < 0) f2 = 0; + sic_newinlet((t_sic *)x, f1); + sic_newinlet((t_sic *)x, f2); + while (nch--) + outlet_new((t_object *)x, &s_signal); + wave_interp(x, 1); + } + return (x); +} + +void wave_tilde_setup(void) +{ + wave_class = class_new(gensym("wave~"), + (t_newmethod)wave_new, + (t_method)wave_free, + sizeof(t_wave), 0, + A_DEFSYM, A_DEFFLOAT, A_DEFFLOAT, A_DEFFLOAT, 0); + arsic_setup(wave_class, wave_dsp, SIC_FLOATTOSIGNAL); + class_addmethod(wave_class, (t_method)wave_set, + gensym("set"), A_SYMBOL, 0); + class_addmethod(wave_class, (t_method)wave_interp, + gensym("interp"), A_FLOAT, 0); +} diff --git a/dumpsetups b/dumpsetups new file mode 100755 index 0000000..e65b265 --- /dev/null +++ b/dumpsetups @@ -0,0 +1,15 @@ +#!/bin/sh +# LATER make this into a regular awk script +DIR=`pwd` +LIB=`basename $DIR` +echo '// Do not edit this file, run "make" instead. + +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ +' +awk '/void .*_setup\(void\)$/&&!/'$LIB'/{print $0";"}' *.c +echo -e '\nvoid all'$LIB's_setup(void)' +echo '{' +awk -F '[ (]' '/void .*_setup\(void\)$/&&!/'$LIB'/{print " "$2"();"}' *.c +echo '}' diff --git a/shared/Makefile b/shared/Makefile new file mode 100644 index 0000000..fc022be --- /dev/null +++ b/shared/Makefile @@ -0,0 +1,2 @@ +ROOT_DIR = .. +include $(ROOT_DIR)/Makefile.common diff --git a/shared/Makefile.dirs b/shared/Makefile.dirs new file mode 100644 index 0000000..d9be5aa --- /dev/null +++ b/shared/Makefile.dirs @@ -0,0 +1 @@ +MIXED_DIRS = common hammer sickle toys unstable diff --git a/shared/Makefile.objects b/shared/Makefile.objects new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/shared/Makefile.objects diff --git a/shared/Makefile.sources b/shared/Makefile.sources new file mode 100644 index 0000000..6e792b8 --- /dev/null +++ b/shared/Makefile.sources @@ -0,0 +1,2 @@ +OTHER_SOURCES = \ +shared.c diff --git a/shared/common/Makefile b/shared/common/Makefile new file mode 100644 index 0000000..5dcb2c8 --- /dev/null +++ b/shared/common/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR = ../.. +include $(ROOT_DIR)/Makefile.common + +all: $(OBJECTS) diff --git a/shared/common/Makefile.objects b/shared/common/Makefile.objects new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/shared/common/Makefile.objects diff --git a/shared/common/Makefile.sources b/shared/common/Makefile.sources new file mode 100644 index 0000000..64da6f8 --- /dev/null +++ b/shared/common/Makefile.sources @@ -0,0 +1,16 @@ +OTHER_SOURCES = \ +bifi.c \ +binport.c \ +dict.c \ +grow.c \ +hyphen.c \ +loud.c \ +mfbb.c \ +mifi.c \ +port.c \ +props.c \ +rand.c \ +sofi.c \ +sq.c \ +squeal.c \ +vefl.c diff --git a/shared/common/bifi.c b/shared/common/bifi.c new file mode 100644 index 0000000..22f3df3 --- /dev/null +++ b/shared/common/bifi.c @@ -0,0 +1,217 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* generic helpers for binary file reading and writing */ + +#ifdef NT +#include <io.h> +#else +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "m_pd.h" +#include "shared.h" +#include "common/bifi.h" + +#if 1 +#define BIFI_VERBOSE +#if 0 +#define BIFI_DEBUG +#endif +#endif + +static int bifi_swapping = 1; /* set in bifi_clear() */ + +/* one helper from g_array.c (the original is global, but since + garray_ambigendian() lacks EXTERN specifier, .dll externs cannot see it; + btw. it has a comment: ``this should be renamed and moved...'') +*/ +static int ambigendian(void) +{ + unsigned short s = 1; + unsigned char c = *(char *)(&s); + return (c==0); +} + +/* two helpers from d_soundfile.c */ +uint32 bifi_swap4(uint32 n) +{ + if (bifi_swapping) + return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | + ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); + else return (n); +} + +uint16 bifi_swap2(uint16 n) +{ + if (bifi_swapping) + return (((n & 0xff) << 8) | ((n & 0xff00) >> 8)); + else return (n); +} + +static void bifi_error_clear(t_bifi *x) +{ + x->b_err = BIFI_ERR_OK; + x->b_syserrno = 0; + errno = 0; +} + +static void bifi_error_set(t_bifi *x, int errcode) +{ + x->b_err = errcode; + x->b_syserrno = errno; + if (errcode != BIFI_ERR_OK && x->b_fp) + { + fclose(x->b_fp); + x->b_fp = 0; + } +#if 0 /* LATER use Pd's own error logging mechanism, maybe by calling this: */ + sys_unixerror((char *)x); /* sys_logerror((char *)x, "...")? */ +#endif +} + +void bifi_clear(t_bifi *x) +{ + bifi_swapping = !ambigendian(); + x->b_fp = 0; + x->b_filename[0] = '\0'; + bifi_error_clear(x); +} + +t_bifi *bifi_new(t_bifi *x, char *hdr, size_t hdrsz) +{ + t_bifi *result = x; + if (result) result->b_selfalloc = 0; + else { + if (!(result = getbytes(sizeof(*result)))) return (0); + result->b_selfalloc = 1; + } + if (hdr || !hdrsz) result->b_hdralloc = 0; + else { + if (!(hdr = getbytes(hdrsz))) + { + if (result->b_selfalloc) freebytes(result, sizeof(*result)); + return (0); + } + result->b_hdralloc = 1; + } + result->b_header = hdr; + result->b_headersize = hdrsz; + bifi_clear(result); + return (result); +} + +void bifi_free(t_bifi *x) +{ + if (x->b_fp) fclose(x->b_fp); + if (x->b_hdralloc) freebytes(x->b_header, x->b_headersize); + if (x->b_selfalloc) freebytes(x, sizeof(*x)); +} + +void bifi_error_report(t_bifi *x) +{ + char *errmess = 0; + switch (x->b_err) + { + case BIFI_ERR_OK: + break; + case BIFI_ERR_OPEN: + errmess = "cannot open"; + break; + case BIFI_ERR_READ: + errmess = "error reading"; + break; + case BIFI_ERR_WRITE: + errmess = "error writing"; + break; + case BIFI_ERR_BADHEADER: + errmess = "missing header of"; + break; + default: + post("binary file i/o unknown error"); + } + if (errmess) + post("%s binary file `%s\' (errno %d: %s)", errmess, + x->b_filename, x->b_syserrno, strerror(x->b_syserrno)); + bifi_error_clear(x); +} + +/* Open file and read in its header (x must be a valid t_bifi pointer, + no checks are being made...) +*/ +int bifi_read_start(t_bifi *x, const char *filename, const char *dirname) +{ + int fd; + char dirbuf[MAXPDSTRING], *nameptr; + + bifi_clear(x); + strcpy(x->b_filename, filename); + if ((fd = open_via_path(dirname, filename, + "", dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + /* Closing/reopening dance. This is unnecessary under linux, and we + could have tried to convert fd to fp (since we prefer using streams), + but under windows open_via_path() returns what seems to be an invalid + fd. LATER try to understand what is going on here... */ + close(fd); + if (dirbuf != nameptr) + { + char *slashpos = dirbuf + strlen(dirbuf); + *slashpos++ = '/'; + /* try not to be dependent on current open_via_path() implementation */ + if (nameptr != slashpos) + strcpy(slashpos, nameptr); + } + sys_unbashfilename(dirbuf, dirbuf); + if (!(x->b_fp = fopen(dirbuf, "rb"))) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + if (x->b_headersize && + fread(x->b_header, 1, x->b_headersize, x->b_fp) < x->b_headersize) + { + bifi_error_set(x, BIFI_ERR_BADHEADER); + return (0); + } + return (1); +} + +/* Open file and write the supplied header (x must be a valid t_bifi pointer + with header data properly filled, no checks are being made...) +*/ +int bifi_write_start(t_bifi *x, const char *filename, const char *dirname) +{ + char fnamebuf[MAXPDSTRING]; + + bifi_clear(x); + strcpy(x->b_filename, filename); + + fnamebuf[0] = 0; + if (*dirname) + strcat(fnamebuf, dirname), strcat(fnamebuf, "/"); + strcat(fnamebuf, filename); + sys_bashfilename(fnamebuf, fnamebuf); + if (!(x->b_fp = fopen(fnamebuf, "wb"))) + { + bifi_error_set(x, BIFI_ERR_OPEN); + return (0); + } + + if (x->b_headersize && + fwrite(x->b_header, 1, x->b_headersize, x->b_fp) < x->b_headersize) + { + bifi_error_set(x, BIFI_ERR_WRITE); + return (0); + } + return (1); +} diff --git a/shared/common/bifi.h b/shared/common/bifi.h new file mode 100644 index 0000000..29fe5ae --- /dev/null +++ b/shared/common/bifi.h @@ -0,0 +1,40 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* generic helpers for binary file reading and writing */ + +#ifndef __BIFI_H__ +#define __BIFI_H__ + +#define BIFI_ERR_OK 0 +#define BIFI_ERR_OPEN -1 +#define BIFI_ERR_READ -2 /* generic read failure */ +#define BIFI_ERR_WRITE -3 /* generic write failure */ +#define BIFI_ERR_BADHEADER -4 /* header missing or short */ + +typedef struct _bifi +{ + int b_selfalloc:1; + int b_hdralloc:1; + char *b_header; + size_t b_headersize; + FILE *b_fp; + char b_filename[MAXPDSTRING]; + int b_err; /* BIFI_ERR code */ + int b_syserrno; /* system error code */ +} t_bifi; + +uint32 bifi_swap4(uint32 n); +uint16 bifi_swap2(uint16 n); + +t_bifi *bifi_new(t_bifi *x, char *hdr, size_t hdrsz); +void bifi_free(t_bifi *x); +void bifi_clear(t_bifi *x); + +int bifi_read_start(t_bifi *x, const char *filename, const char *dirname); +int bifi_write_start(t_bifi *x, const char *filename, const char *dirname); + +void bifi_error_report(t_bifi *x); + +#endif diff --git a/shared/common/binport.c b/shared/common/binport.c new file mode 100644 index 0000000..05cc5df --- /dev/null +++ b/shared/common/binport.c @@ -0,0 +1,559 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdlib.h> +#include <stdio.h> +#include <stdarg.h> +#include <string.h> + +#define BINPORT_MAXSTRING 256 +#define BINPORT_SYMGROW 64 + +#ifndef BINPORT_STANDALONE +/* load max binary file to a binbuf */ + +#include "m_pd.h" + +#else +/* make a max-textual listing from a max binary file */ + +/* This is a standalone version of a ``max binary to binbuf'' module. + It uses certain Pd calls and structs, which are duplicated below. + LATER should be linked to the Pd API library. */ + +#define BINPORT_VERBOSE +//#define BINPORT_DEBUG + +#endif + +#include "binport.h" + +static void binport_error(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "ERROR (binport): "); + vfprintf(stderr, fmt, ap); + putc('\n', stderr); + va_end(ap); +} + +static void binport_warning(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "warning (binport): "); + vfprintf(stderr, fmt, ap); + putc('\n', stderr); + va_end(ap); +} + +static void binport_bug(char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "BUG (binport): "); + vfprintf(stderr, fmt, ap); + putc('\n', stderr); + va_end(ap); +} + +#ifdef BINPORT_STANDALONE + +typedef int t_int; +typedef float t_float; + +typedef struct _symbol +{ + char *s_name; + void *s_thing; + struct _symbol *s_next; +} t_symbol; + +typedef union word +{ + t_float w_float; + t_symbol *w_symbol; + int w_index; +} t_word; + +typedef enum +{ + A_NULL, + A_FLOAT, + A_SYMBOL, + A_POINTER, + A_SEMI, + A_COMMA, + A_DEFFLOAT, + A_DEFSYM, + A_DOLLAR, + A_DOLLSYM, + A_GIMME, + A_CANT +} t_atomtype; + +typedef struct _atom +{ + t_atomtype a_type; + union word a_w; +} t_atom; + +void *getbytes(size_t nbytes) +{ + void *ret; + if (nbytes < 1) nbytes = 1; + ret = (void *)calloc(nbytes, 1); + if (!ret) + binport_error("getbytes() failed -- out of memory"); + return (ret); +} + +void *resizebytes(void *old, size_t oldsize, size_t newsize) +{ + void *ret; + if (newsize < 1) newsize = 1; + if (oldsize < 1) oldsize = 1; + ret = (void *)realloc((char *)old, newsize); + if (newsize > oldsize && ret) + memset(((char *)ret) + oldsize, 0, newsize - oldsize); + if (!ret) + binport_error("resizebytes() failed -- out of memory"); + return (ret); +} + +void freebytes(void *fatso, size_t nbytes) +{ + free(fatso); +} + +#define HASHSIZE 1024 + +static t_symbol *symhash[HASHSIZE]; + +t_symbol *dogensym(char *s, t_symbol *oldsym) +{ + t_symbol **sym1, *sym2; + unsigned int hash1 = 0, hash2 = 0; + int length = 0; + char *s2 = s; + while (*s2) + { + hash1 += *s2; + hash2 += hash1; + length++; + s2++; + } + sym1 = symhash + (hash2 & (HASHSIZE-1)); + while (sym2 = *sym1) + { + if (!strcmp(sym2->s_name, s)) return(sym2); + sym1 = &sym2->s_next; + } + if (oldsym) sym2 = oldsym; + else + { + sym2 = (t_symbol *)getbytes(sizeof(*sym2)); + sym2->s_name = getbytes(length+1); + sym2->s_next = 0; + sym2->s_thing = 0; + strcpy(sym2->s_name, s); + } + *sym1 = sym2; + return (sym2); +} + +t_symbol *gensym(char *s) +{ + return(dogensym(s, 0)); +} + +#endif /* end of Pd API */ + +/* clumsy... LATER find a better way */ +#ifdef BINPORT_STANDALONE +#define A_INT (A_CANT + 1) +#endif + +static int binport_getint(t_atom *ap) +{ +#ifdef A_INT + return (*(int *)&ap->a_w); +#else + return (ap->a_w.w_float); +#endif +} + +static void binport_setint(t_atom *ap, int i) +{ +#ifdef A_INT + ap->a_type = A_INT; + *(int *)&ap->a_w = i; +#else + SETFLOAT(ap, (float)i); +#endif +} + +static void binport_setfloat(t_atom *ap, float f) +{ + ap->a_type = A_FLOAT; + ap->a_w.w_float = f; +} + +typedef struct _binport +{ + FILE *b_fp; + int b_nsymbols; + int b_symsize; + t_symbol **b_symtable; +} t_binport; + +static int binport_getbuf(t_binport *bp, char *buf, size_t sz) +{ + return (fread(buf, 1, sz, bp->b_fp) == sz); +} + +static int binport_getbyte(t_binport *bp, unsigned char *buf) +{ + int c; + if ((c = fgetc(bp->b_fp)) == EOF) + return (0); + *buf = (unsigned char)c; + return (1); +} + +static int binport_getstring(t_binport *bp, char *buf) +{ + int c, i = 0; + while (c = fgetc(bp->b_fp)) + { + if (c == EOF) + return (0); + if (++i < BINPORT_MAXSTRING) + *buf++ = (unsigned char)c; + } + *buf = '\0'; + if (i >= BINPORT_MAXSTRING) + binport_warning("symbol string too long, skipped"); + return (1); +} + +static t_symbol *binport_makesymbol(t_binport *bp, int id) +{ + char s[BINPORT_MAXSTRING]; + if (id < bp->b_nsymbols) + binport_bug("symbol id mismatch"); + else if (id > bp->b_nsymbols) + binport_error("unexpected symbol id"); + else if (binport_getstring(bp, s)) + { + int reqsize = ++bp->b_nsymbols; + if (reqsize > bp->b_symsize) + { + reqsize += (BINPORT_SYMGROW - 1); +#ifdef BINPORT_DEBUG + binport_warning("resizing symbol table to %d elements", reqsize); +#endif + if (bp->b_symtable = + resizebytes(bp->b_symtable, + bp->b_symsize * sizeof(*bp->b_symtable), + reqsize * sizeof(*bp->b_symtable))) + bp->b_symsize = reqsize; + else + { + bp->b_nsymbols = bp->b_symsize = 0; + return (0); + } + } + return (bp->b_symtable[id] = gensym(s)); + } + return (0); +} + +static t_symbol *binport_getsymbol(t_binport *bp, int id) +{ + if (id < bp->b_nsymbols) + return (bp->b_symtable[id]); + else + return (binport_makesymbol(bp, id)); +} + +static int binport_setsymbol(t_binport *bp, t_atom *ap, int id) +{ + t_symbol *s = binport_getsymbol(bp, id); + if (s) + { + ap->a_type = A_SYMBOL; + ap->a_w.w_symbol = s; + } + return (s != 0); +} + +static int binport_nextatom(t_binport *bp, t_atom *ap) +{ + unsigned char opcode; + int opval; + char buf[64]; + if (!binport_getbyte(bp, &opcode)) + goto bad; + opval = opcode & 0x0f; + switch (opcode >> 4) + { + case 1: /* variable length int, + opval: length (number of bytes that follow) */ + if (!binport_getbuf(bp, buf, opval)) + goto bad; + else + { + unsigned char *p = (unsigned char *)buf + opval; + int i = 0; + while (opval--) i = (i << 8) | *--p; + if (opcode == 0x12) /* FIXME */ + i = (short)i; + binport_setint(ap, i); + } + break; + case 2: /* variable length float, + opval: length (number of bytes that follow) */ + if (!binport_getbuf(bp, buf, opval)) + goto bad; + else + { + unsigned char *p = (unsigned char *)buf + opval; + int i = 0; + while (opval--) i = (i << 8) | *--p; + binport_setfloat(ap, *(t_float *)&i); + } + break; + case 3: /* variable length symbol id, + opval: length (number of bytes that follow) */ + if (!binport_getbuf(bp, buf, opval)) + goto bad; + else + { + unsigned char *p = (unsigned char *)buf + opval; + int i = 0; + while (opval--) i = (i << 8) | *--p; + if (!binport_setsymbol(bp, ap, i)) + goto bad; + } + break; + case 5: /* half-byte int */ + binport_setint(ap, opval); + break; + case 7: /* half-byte symbol id */ + if (!binport_setsymbol(bp, ap, opval)) + goto bad; + break; + case 12: /* #number */ + sprintf(buf, "#%d", opval); + ap->a_type = A_SYMBOL; + ap->a_w.w_symbol = gensym(buf); + break; + case 13: /* #symbol id, + opval: length (number of bytes that follow) */ + if (!binport_getbuf(bp, buf, opval)) + goto bad; + else + { + unsigned char *p = (unsigned char *)buf + opval; + int i = 0; + while (opval--) i = (i << 8) | *--p; + if (!binport_setsymbol(bp, ap, i)) + goto bad; + } + sprintf(buf, "#%s", ap->a_w.w_symbol->s_name); +#ifdef BINPORT_DEBUG + binport_warning(buf); +#endif + ap->a_w.w_symbol = gensym(buf); + break; + default: + switch (opcode) + { + case 0xa0: + ap->a_type = A_SEMI; + break; + default: + goto unknown; + } + } + return (1); +unknown: + binport_error("unknown opcode %x", (int)opcode); +bad: + return (0); +} + +static void binport_free(t_binport *bp) +{ + fclose(bp->b_fp); + freebytes(bp->b_symtable, bp->b_symsize * sizeof(*bp->b_symtable)); + freebytes(bp, sizeof(*bp)); +} + +static t_binport *binport_new(FILE *fp, int *ftypep) +{ + static char binport_header[4] = { 2, 0, 0, 0 }; + char header[4]; + *ftypep = BINPORT_INVALID; + if (fread(header, 1, 4, fp) == 4) + { + if (memcmp(header, binport_header, 4)) + { + if (memcmp(header, "max", 3)) + { + if (header[0] == '#') /* LATER rethink */ + *ftypep = BINPORT_PDFILE; +#ifdef BINPORT_VERBOSE + else binport_warning("unknown header: %x %x %x %x", + (int)header[0], (int)header[1], + (int)header[2], (int)header[3]); +#endif + } + else *ftypep = BINPORT_MAXTEXT; + } + else + { + t_binport *bp = getbytes(sizeof(*bp)); + bp->b_fp = fp; + bp->b_nsymbols = 0; + bp->b_symsize = BINPORT_SYMGROW; + bp->b_symtable = getbytes(bp->b_symsize * sizeof(*bp->b_symtable)); + *ftypep = BINPORT_OK; + return (bp); + } + } +#ifdef BINPORT_VERBOSE + else binport_warning("file too short"); +#endif + fclose(fp); + return (0); +} + +#ifndef BINPORT_STANDALONE + +/* LATER deal with corrupt binary files? */ +int binport_read(t_binbuf *bb, char *filename, char *dirname) +{ + FILE *fp; + char namebuf[MAXPDSTRING]; + namebuf[0] = 0; + if (*dirname) + strcat(namebuf, dirname), strcat(namebuf, "/"); + strcat(namebuf, filename); + sys_bashfilename(namebuf, namebuf); + if (fp = fopen(namebuf, "rb")) + { + int ftype; + t_binport *bp = binport_new(fp, &ftype); + if (bp) + { + t_atom at; + while (binport_nextatom(bp, &at)) + binbuf_add(bb, 1, &at); + binport_free(bp); + return (BINPORT_OK); + } + else if (ftype == BINPORT_MAXTEXT || ftype == BINPORT_PDFILE) + return (ftype); + else + binport_error("\"%s\" doesn't look like a patch file", filename); + } + else binport_bug("cannot open file"); + return (BINPORT_INVALID); +} + +#else + +static void binport_atomstring(t_atom *ap, char *buf, int bufsize) +{ + char *sp, *bp, *ep; + switch(ap->a_type) + { + case A_SEMI: + strcpy(buf, ";"); break; + case A_COMMA: + strcpy(buf, ","); break; + case A_INT: + sprintf(buf, "%d", binport_getint(ap)); break; + case A_FLOAT: + sprintf(buf, "%#f", ap->a_w.w_float); + ep = buf + strlen(buf) - 1; + while (ep > buf && *ep == '0') *ep-- = 0; + break; + case A_SYMBOL: + sp = ap->a_w.w_symbol->s_name; + bp = buf; + ep = buf + (bufsize-5); + while (bp < ep && *sp) + { + if (*sp == ';' || *sp == ',' || *sp == '\\' || + (*sp == '$' && bp == buf && sp[1] >= '0' && sp[1] <= '9')) + *bp++ = '\\'; + if ((unsigned char)*sp < 127) + *bp++ = *sp++; + else + /* FIXME this is temporary -- codepage horror */ + sprintf(bp, "\\%.3o", (unsigned char)*sp++), bp += 4; + } + if (*sp) *bp++ = '*'; + *bp = 0; + break; + case A_DOLLAR: + sprintf(buf, "$%d", ap->a_w.w_index); + break; + case A_DOLLSYM: + sprintf(buf, "$%s", ap->a_w.w_symbol->s_name); + break; + default: + binport_bug("bad atom type"); + strcpy(buf, "???"); + } +} + +int main(int ac, char **av) +{ + if (ac > 1) + { + FILE *fp = fopen(av[1], "rb"); + if (fp) + { + int ftype; + t_binport *bp = binport_new(fp, &ftype); + if (bp) + { + char buf[BINPORT_MAXSTRING]; + t_atom at; + int ac = 0; + while (binport_nextatom(bp, &at)) + { + if (at.a_type == A_SEMI) + { + fputs(";\n", stdout); + ac = 0; + } + else + { + if (ac++) fputc(' ', stdout); + binport_atomstring(&at, buf, BINPORT_MAXSTRING); + fputs(buf, stdout); + } + } + binport_free(bp); + } + else if (ftype == BINPORT_MAXTEXT) + binport_warning("\"%s\" looks like a Max text file", av[1]); + else if (ftype == BINPORT_PDFILE) + binport_warning("\"%s\" looks like a Pd patch file", av[1]); + else + binport_error("\"%s\" doesn't look like a patch file", av[1]); + } + else binport_error("cannot open file \"%s\"", av[1]); + } + else binport_error("what file?"); + return (0); +} + +#endif diff --git a/shared/common/binport.h b/shared/common/binport.h new file mode 100644 index 0000000..0b6b607 --- /dev/null +++ b/shared/common/binport.h @@ -0,0 +1,15 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __BINPORT_H__ +#define __BINPORT_H__ + +enum { BINPORT_OK, BINPORT_MAXTEXT, BINPORT_PDFILE, + BINPORT_INVALID, BINPORT_CORRUPT }; + +#ifndef BINPORT_STANDALONE +int binport_read(t_binbuf *bb, char *filename, char *dirname); +#endif + +#endif diff --git a/shared/common/grow.c b/shared/common/grow.c new file mode 100644 index 0000000..f02509a --- /dev/null +++ b/shared/common/grow.c @@ -0,0 +1,105 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* LATER generic handling of reentrant output request and self-invoked set */ + +#include <string.h> +#include "m_pd.h" +#include "common/grow.h" + +/* Prior to this call a caller is supposed to check for *nrequested > *sizep. + Returns a reallocated buffer's pointer (success) or a given 'bufini' + default value (failure). + Upon return *nrequested contains the actual number of elements: + requested (success) or a given default value of 'inisize' (failure). */ +void *grow_nodata(int *nrequested, int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize) +{ + int newsize = *sizep * 2; + while (newsize < *nrequested) newsize *= 2; + if (bufp == bufini) + bufp = getbytes(newsize * typesize); + else + bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize); + if (bufp) + { + *sizep = newsize; + return (bufp); + } + else + { + *nrequested = *sizep = inisize; + return (bufini); + } +} + +/* Like grow_nodata(), but preserving first *nexisting elements. */ +void *grow_withdata(int *nrequested, int *nexisting, + int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize) +{ + int newsize = *sizep * 2; + while (newsize < *nrequested) newsize *= 2; + if (bufp == bufini) + { + if (!(bufp = getbytes(newsize * typesize))) + { + *nrequested = *sizep = inisize; + return (bufini); + } + *sizep = newsize; + memcpy(bufp, bufini, *nexisting * typesize); + } + else + { + int oldsize = *sizep; + if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize))) + { + *nrequested = *sizep = inisize; + *nexisting = 0; + return (bufini); + } + *sizep = newsize; + } + return (bufp); +} + +/* Like grow_nodata(), but preserving a 'tail' of *nexisting elements, + starting from *startp. */ +/* LATER rethink handling of a start pointer (clumsy now) */ +void *grow_withtail(int *nrequested, int *nexisting, char **startp, + int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize) +{ + int newsize = *sizep * 2; + while (newsize < *nrequested) newsize *= 2; + if (bufp == bufini) + { + char *oldstart = *startp; + if (!(bufp = getbytes(newsize * typesize))) + { + *nrequested = *sizep = inisize; + return (bufini); + } + *startp = (char *)bufp + (newsize - *nexisting) * typesize; + *sizep = newsize; + memcpy(*startp, oldstart, *nexisting * typesize); + } + else + { + int oldsize = *sizep; + if (!(bufp = resizebytes(bufp, *sizep * typesize, newsize * typesize))) + { + *startp = (char *)bufini + inisize * typesize; + *nrequested = *sizep = inisize; + *nexisting = 0; + return (bufini); + } + *startp = (char *)bufp + (newsize - *nexisting) * typesize; + *sizep = newsize; + memmove(*startp, (char *)bufp + (oldsize - *nexisting) * typesize, + *nexisting * typesize); + } + return (bufp); +} diff --git a/shared/common/grow.h b/shared/common/grow.h new file mode 100644 index 0000000..1749cfc --- /dev/null +++ b/shared/common/grow.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __GROW_H__ +#define __GROW_H__ + +void *grow_nodata(int *nrequested, int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize); +void *grow_withdata(int *nrequested, int *nexisting, + int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize); +void *grow_withtail(int *nrequested, int *nexisting, char **startp, + int *sizep, void *bufp, + int inisize, void *bufini, size_t typesize); + +#endif diff --git a/shared/common/loud.c b/shared/common/loud.c new file mode 100644 index 0000000..638f431 --- /dev/null +++ b/shared/common/loud.c @@ -0,0 +1,210 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <errno.h> +#include "m_pd.h" +#include "common/loud.h" + +#define LOUD_ERROR_DEFAULT "error (miXed): " + +/* LATER move it somewhere else */ +t_symbol *loud_floatsym(void) +{ + static t_symbol *s = 0; + return (s ? s : (s = gensym("noninteger float"))); +} + +/* LATER move it somewhere else */ +char *loud_symbolname(t_symbol *s, char *nullname) +{ + return (s && s != &s_ ? s->s_name : nullname); +} + +/* LATER move it somewhere else */ +char *loud_ordinal(int n) +{ + static char buf[16]; /* assuming 10-digit INT_MAX */ + sprintf(buf, "%dth", n); + if (n < 0) n = -n; + n %= 100; + if (n > 20) n %= 10; + if (n && n <= 3) + { + char *ptr = buf + strlen(buf) - 2; + switch (n) + { + case 1: strcpy(ptr, "st"); break; + case 2: strcpy(ptr, "nd"); break; + case 3: strcpy(ptr, "rd"); break; + } + } + return (buf); +} + +void loud_error(t_pd *x, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + if (x) + { + char buf[MAXPDSTRING]; + fprintf(stderr, "%s's ", class_getname(*x)); + vsprintf(buf, fmt, ap); + pd_error(x, buf); + } + else + { + fputs(LOUD_ERROR_DEFAULT, stderr); + vfprintf(stderr, fmt, ap); + putc('\n', stderr); + } + va_end(ap); +} + +void loud_errand(t_pd *x, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%*s", (int)(x ? strlen(class_getname(*x)) + 10 + : strlen(LOUD_ERROR_DEFAULT)), ""); + vfprintf(stderr, fmt, ap); + putc('\n', stderr); + va_end(ap); +} + +void loud_syserror(t_pd *x, char *msg) +{ + if (msg) + loud_error(x, "%s (%s)", msg, strerror(errno)); + else + loud_error(x, strerror(errno)); +} + +void loud_nomethod(t_pd *x, t_symbol *s) +{ + loud_error(x, "doesn't understand \"%s\"", s->s_name); +} + +void loud_messarg(t_pd *x, t_symbol *s) +{ + loud_error(x, "bad arguments for message \"%s\"", s->s_name); +} + +int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess) +{ + if ((*valuep = (int)f) == f) + return (1); + else + { + if (mess == &s_float) + loud_nomethod(x, loud_floatsym()); + else if (mess) + loud_error(x, "\"%s\" argument invalid for message \"%s\"", + loud_floatsym()->s_name, mess->s_name); + return (0); + } +} + +void loud_classarg(t_class *c) +{ + loud_error(0, "missing or bad arguments in \"%s\"", class_getname(c)); +} + +void loud_warning(t_pd *x, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "warning (%s): ", (x ? class_getname(*x) : "miXed")); + vfprintf(stderr, fmt, ap); + va_end(ap); + putc('\n', stderr); +} + +void loud_notimplemented(t_pd *x, char *name) +{ + if (name) + loud_warning(x, "\"%s\" method not implemented (yet)", name); + else + loud_warning(x, "not implemented (yet)"); +} + +void loud_incompatible(t_class *c, char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "'%s' class incompatibility warning:\n\t", + class_getname(c)); + vfprintf(stderr, fmt, ap); + va_end(ap); + putc('\n', stderr); +} + +void loud_incompatible_max(t_class *c, int maxmax, char *what) +{ + loud_incompatible(c, "more than %d %s requested", maxmax, what); +} + +int loud_floatarg(t_class *c, int which, int ac, t_atom *av, + t_float *vp, t_float minval, t_float maxval, + int underaction, int overaction, char *what) +{ + int result = LOUD_ARGOK; + if (which < ac) + { + av += which; + if (av->a_type == A_FLOAT) + { + t_float f = av->a_w.w_float; + if (f < minval) + { + *vp = (underaction & LOUD_CLIP ? minval : f); + if (underaction) + result = LOUD_ARGUNDER; + } + else if (f > maxval) + { + *vp = (overaction & LOUD_CLIP ? maxval : f); + if (overaction) + result = LOUD_ARGOVER; + } + else *vp = f; + } + else result = LOUD_ARGTYPE; + } + else result = LOUD_ARGMISSING; + if (what) + { + switch (result) + { + case LOUD_ARGUNDER: + if (underaction & LOUD_WARN) + { + if (underaction & LOUD_CLIP) + loud_warning(&c, "%s rounded up to %g", what, minval); + else + loud_incompatible(c, "less than %g %s requested", + minval, what); + } + break; + case LOUD_ARGOVER: + if (overaction & LOUD_WARN) + { + if (overaction & LOUD_CLIP) + loud_warning(&c, "%s truncated to %g", what, maxval); + else + loud_incompatible(c, "more than %g %s requested", + maxval, what); + } + break; + case LOUD_ARGTYPE: + loud_error(0, "bad argument %d (%s)", which, class_getname(c)); + break; + default:; + } + } + return (result); +} diff --git a/shared/common/loud.h b/shared/common/loud.h new file mode 100644 index 0000000..17c02bf --- /dev/null +++ b/shared/common/loud.h @@ -0,0 +1,31 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __LOUD_H__ +#define __LOUD_H__ + +#define LOUD_CLIP 1 +#define LOUD_WARN 2 + +enum { LOUD_ARGOK, LOUD_ARGUNDER, LOUD_ARGOVER, LOUD_ARGTYPE, LOUD_ARGMISSING }; + +t_symbol *loud_floatsym(void); +char *loud_symbolname(t_symbol *s, char *nullname); +char *loud_ordinal(int n); +void loud_error(t_pd *x, char *fmt, ...); +void loud_errand(t_pd *x, char *fmt, ...); +void loud_syserror(t_pd *x, char *msg); +void loud_nomethod(t_pd *x, t_symbol *s); +void loud_messarg(t_pd *x, t_symbol *s); +int loud_checkint(t_pd *x, t_float f, int *valuep, t_symbol *mess); +void loud_classarg(t_class *c); +void loud_warning(t_pd *x, char *fmt, ...); +void loud_notimplemented(t_pd *x, char *name); +void loud_incompatible(t_class *c, char *fmt, ...); +void loud_incompatible_max(t_class *c, int maxmax, char *what); +int loud_floatarg(t_class *c, int which, int ac, t_atom *av, + t_float *vp, t_float minval, t_float maxval, + int underaction, int overaction, char *what); + +#endif diff --git a/shared/common/mifi.c b/shared/common/mifi.c new file mode 100644 index 0000000..ad16b3b --- /dev/null +++ b/shared/common/mifi.c @@ -0,0 +1,867 @@ +/* Copyright (c) 2001-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* reading/writing midifiles, a prototype version */ + +#ifdef NT +#include <io.h> +#else +#include <unistd.h> +#endif +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include "m_pd.h" +#include "shared.h" +#include "common/sq.h" +#include "common/bifi.h" +#include "common/mifi.h" + +#if 1 +#define MIFI_VERBOSE +#if 0 +#define MIFI_DEBUG +#endif +#endif + +#define MIFI_SHORTEST_EVENT 2 /* singlebyte delta and one databyte */ +#define MIFI_EVENT_NALLOC 32 /* LATER do some research (average max?) */ +#define MIFI_HEADER_SIZE 14 /* in case t_mifi_header is padded to 16 */ +#define MIFI_HEADERDATA_SIZE 6 +#define MIFI_TRACKHEADER_SIZE 8 + +/* header structures for midifile and track */ + +typedef struct _mifi_header +{ + char h_type[4]; + uint32 h_length; + uint16 h_format; + uint16 h_ntracks; + uint16 h_division; +} t_mifi_header; + +typedef struct _mifi_trackheader +{ + char h_type[4]; + uint32 h_length; +} t_mifi_trackheader; + +/* reading helpers */ + +static void mifi_earlyeof(t_mifi_stream *x) +{ + x->s_bytesleft = 0; + x->s_eof = 1; +} + +/* Get next byte from track data. + On error: return 0 (which is a valid result) and set x->s_eof. +*/ +static uchar mifi_getbyte(t_mifi_stream *x) +{ + if (x->s_bytesleft) + { + int c; + if ((c = fgetc(x->s_fp)) == EOF) + { + mifi_earlyeof(x); + return (0); + } + else { + x->s_bytesleft--; + return ((uchar)c); + } + } + else return (0); +} + +static uint32 mifi_readbytes(t_mifi_stream *x, uchar *buf, uint32 size) +{ + size_t res; + if (size > x->s_bytesleft) + size = x->s_bytesleft; + if ((res = fread(buf, 1, (size_t)size, x->s_fp)) == size) + x->s_bytesleft -= res; + else + mifi_earlyeof(x); + return (res); +} + +static int mifi_skipbytes(t_mifi_stream *x, uint32 size) +{ + if (size > x->s_bytesleft) + size = x->s_bytesleft; + if (size) + { + int res = fseek(x->s_fp, size, SEEK_CUR); + if (res < 0) + mifi_earlyeof(x); + else + x->s_bytesleft -= size; + return res; + } + else return (0); +} + +/* helpers handling variable-length quantities */ + +static size_t mifi_writevarlen(t_mifi_stream *x, uint32 n) +{ + uint32 buf = n & 0x7f; + size_t length = 1; + while ((n >>= 7) > 0) + { + buf <<= 8; + buf |= 0x80; + buf += n & 0x7f; + length++; + } + return ((fwrite(&buf, 1, length, x->s_fp) == length) ? length : 0); +} + +static uint32 mifi_readvarlen(t_mifi_stream *x) +{ + uint32 n = 0; + uchar c; + uint32 count = x->s_bytesleft; + if (count > 4) count = 4; + while (count--) + { + n = (n << 7) + ((c = mifi_getbyte(x)) & 0x7f); + if ((c & 0x80) == 0) + break; + } + return (n); +} + +/* other helpers */ + +static int mifi_read_start_track(t_mifi_stream *x) +{ + t_mifi_trackheader header; + long skip; + int notyet = 1; + do { + if (fread(&header, 1, + MIFI_TRACKHEADER_SIZE, x->s_fp) < MIFI_TRACKHEADER_SIZE) + goto nomoretracks; + header.h_length = bifi_swap4(header.h_length); + if (strncmp(header.h_type, "MTrk", 4)) + { + char buf[5]; + strncpy(buf, header.h_type, 4); + buf[5] = '\0'; + if (x->s_anapass) + post("unknown chunk %s in midifile -- skipped", buf); + } + else if (header.h_length < MIFI_SHORTEST_EVENT) + { + if (x->s_anapass) post("empty track in midifile -- skipped"); + } + else notyet = 0; + if (notyet && (skip = header.h_length) && + fseek(x->s_fp, skip, SEEK_CUR) < 0) + goto nomoretracks; + } while (notyet); + + x->s_track++; + x->s_newtrack = 1; + x->s_status = x->s_channel = 0; + x->s_bytesleft = header.h_length; + x->s_time = 0; + + return (1); +nomoretracks: + if (x->s_track == 0) + if (x->s_anapass) post("no valid miditracks"); + return (0); +} + +/* public interface */ + +t_mifi_event *mifi_event_new(void) +{ + t_mifi_event *e = getbytes(sizeof(*e)); + if (e && !(e->e_data = getbytes(e->e_bufsize = MIFI_EVENT_NALLOC))) + { + freebytes(e, sizeof(*e)); + return (0); + } + return (e); +} + +void mifi_event_free(t_mifi_event *e) +{ + freebytes(e->e_data, e->e_bufsize); + freebytes(e, sizeof(*e)); +} + +int mifi_event_settext(t_mifi_event *e, int type, char *text) +{ + e->e_delay = 0; + e->e_status = MIFI_EVENT_META; + e->e_meta = type; + e->e_length = strlen(text); + if (squb_checksize(e, e->e_length + 1, 1) <= e->e_length) + { + e->e_length = 0; + return (0); + } + strcpy(e->e_data, text); + return (1); +} + +void mifi_event_printmeta(t_mifi_event *e) +{ + static int isprintable[MIFI_META_MAXPRINTABLE+1] = + { +#ifdef MIFI_DEBUG + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +#elif defined MIFI_VERBOSE + 0, 0, 1, 1, 1, 1, 1, 1 +#endif + }; + static char *printformat[MIFI_META_MAXPRINTABLE+1] = + { + "", "text: %s", "copyright: %s", "track name: %s", + "instrument name: %s", "lyric: %s", "marker: %s", "cue point: %s" + }; + if (e->e_meta <= MIFI_META_MAXPRINTABLE) + { + if (isprintable[e->e_meta] && printformat[e->e_meta]) + post(printformat[e->e_meta], e->e_data); + } +#ifdef MIFI_DEBUG /* in verbose mode tempo printout done only after sorting */ + else if (e->e_meta == MIFI_META_TEMPO) + { + int tempo = bifi_swap4(*(uint32*)e->e_data); + post("tempo %d after %d", tempo, e->e_delay); + } +#endif +} + +void mifi_stream_reset(t_mifi_stream *x) +{ + sq_reset(x); + x->s_status = x->s_channel = 0; + x->s_timecoef = sq_msecs2ticks(x, 0); + x->s_bytesleft = 0; +} + +t_mifi_stream *mifi_stream_new(void) +{ + t_mifi_stream *x = sq_new(); + if (x) + { + if (x->s_auxeve = mifi_event_new()) + { + x->s_hdtracks = 1; + x->s_alltracks = 0; + mifi_stream_reset(x); /* LATER avoid calling sq_reset() twice */ + } + else + { + mifi_stream_free(x); + return (0); + } + } + return (x); +} + +void mifi_stream_free(t_mifi_stream *x) +{ + if (x->s_auxeve) + mifi_event_free(x->s_auxeve); + sq_free(x); +} + +/* Open midifile for reading, parse the header. May be used as t_mifi_stream + allocator (if x is a null pointer), to be freed by mifi_read_end() or + explicitly. + + Return value: null on error, else x if passed a valid pointer, else pointer + to an allocated structure. +*/ +t_mifi_stream *mifi_read_start(t_mifi_stream *x, + const char *filename, const char *dirname, + int complain) +{ + t_mifi_stream *result = x; + t_bifi bifi; + t_bifi *bp = &bifi; + t_mifi_header header; + long skip; + + bifi_new(bp, (char *)&header, MIFI_HEADER_SIZE); + if (!bifi_read_start(bp, filename, dirname)) + { + bifi_error_report(bp); + bifi_free(bp); + return (0); + } + if (strncmp(header.h_type, "MThd", 4)) + goto badheader; + header.h_length = bifi_swap4(header.h_length); + if (header.h_length < MIFI_HEADERDATA_SIZE) + goto badheader; + if (skip = header.h_length - MIFI_HEADERDATA_SIZE) + { + post("%ld extra bytes of midifile header -- skipped", skip); + if (fseek(bp->b_fp, skip, SEEK_CUR) < 0) + goto badstart; + } + + /* since we will tolerate other incompatibilities, now we can allocate */ + if (x) mifi_stream_reset(x); + else + { + if (!(result = mifi_stream_new())) + goto badstart; + result->s_autoalloc = 1; + } + result->s_fp = bp->b_fp; + result->s_format = bifi_swap2(header.h_format); + result->s_hdtracks = bifi_swap2(header.h_ntracks); + result->s_nticks = bifi_swap2(header.h_division); + if (result->s_nticks & 0x8000) + { + result->s_nframes = (result->s_nticks >> 8); + result->s_nticks &= 0xff; + } + else result->s_nframes = 0; + if (result->s_nticks == 0) + goto badheader; + + return (result); +badheader: + if (complain) + post("`%s\' is not a valid midifile", filename); +badstart: + if (result && !x) mifi_stream_free(result); + bifi_free(bp); + return (0); +} + +int mifi_read_restart(t_mifi_stream *x) +{ + FILE *fp = x->s_fp; + mifi_stream_reset(x); + x->s_anapass = 0; + x->s_fp = fp; + return (fseek(fp, 0, SEEK_SET) ? 0 : 1); +} + +/* Close midifile and free t_mifi_stream if it was allocated + by mifi_read_start() */ +void mifi_read_end(t_mifi_stream *x) +{ + if (x->s_fp) fclose(x->s_fp); + if (x->s_autoalloc) mifi_stream_free(x); +} + +/* Read next event from midifile. + Return value: see #defines in mifi.h. +*/ +int mifi_read_event(t_mifi_stream *x, t_mifi_event *e) +{ + uchar status, channel; + uint32 length; + + x->s_newtrack = 0; +nextattempt: + if (x->s_bytesleft < MIFI_SHORTEST_EVENT && !mifi_read_start_track(x)) + return (MIFI_READ_EOF); + + x->s_time += (e->e_delay = mifi_readvarlen(x)); + + if ((status = mifi_getbyte(x)) < 0x80) + { + if (MIFI_IS_CHANNEL(x->s_status)) + { + e->e_data[0] = status; + e->e_length = 1; + status = x->s_status; + e->e_channel = x->s_channel; + } + else { + if (x->s_anapass) + post("missing running status in midifile -- skip to end of track"); + goto endoftrack; + } + } + else e->e_length = 0; + + /* channel message */ + if (status < 0xf0) + { + if (e->e_length == 0) + { + e->e_data[0] = mifi_getbyte(x); + e->e_length = 1; + x->s_status = status & 0xf0; + x->s_channel = e->e_channel = status & 0x0f; + status = x->s_status; + } + if (!MIFI_ONE_DATABYTE(status)) + { + e->e_data[1] = mifi_getbyte(x); + e->e_length = 2; + } + } + + /* system exclusive */ + else if (status == MIFI_SYSEX_FIRST || status == MIFI_SYSEX_NEXT) + { + /* LATER choose the right way -- + do we really need all those huge bulk dumps? */ + length = mifi_readvarlen(x); + if (squb_checksize(e, length, 1) < length) + { + if (mifi_skipbytes(x, length) < 0) + return (MIFI_READ_FATAL); + goto nextattempt; + } + if (mifi_readbytes(x, e->e_data, length) != length) + return (MIFI_READ_FATAL); + e->e_length = length; +#ifdef MIFI_VERBOSE + if (x->s_anapass) post("got %d bytes of sysex", length); +#endif + } + + /* meta-event */ + else if (status == MIFI_EVENT_META) + { + e->e_meta = mifi_getbyte(x); + length = mifi_readvarlen(x); + if (e->e_meta > 127) + { + /* try to skip corrupted meta-event (quietly) */ +#ifdef MIFI_VERBOSE + if (x->s_anapass) post("bad meta: %d > 127", e->e_meta); +#endif + if (mifi_skipbytes(x, length) < 0) + return (MIFI_READ_FATAL); + goto nextattempt; + } + switch (e->e_meta) + { + case MIFI_META_EOT: + if (length) + { + /* corrupted eot: ignore and skip to the real end of track */ +#ifdef MIFI_VERBOSE + if (x->s_anapass) post("corrupted eot, length %d", length); +#endif + goto endoftrack; + } + break; + case MIFI_META_TEMPO: + if (length != 3) + { + if (x->s_anapass) + post("corrupted event in midifile -- skip to end of track"); + goto endoftrack; + } + if (mifi_readbytes(x, e->e_data+1, 3) != 3) + return (MIFI_READ_FATAL); + e->e_data[0] = 0; + x->s_tempo = bifi_swap4(*(uint32*)e->e_data); + break; + default: + if (squb_checksize(e, length + 1, 1) <= length) + { + if (mifi_skipbytes(x, length) < 0) + return (MIFI_READ_FATAL); + goto nextattempt; + } + if (mifi_readbytes(x, e->e_data, length) != length) + return (MIFI_READ_FATAL); + e->e_length = length; + if (e->e_meta && e->e_meta <= MIFI_META_MAXPRINTABLE) + e->e_data[length] = '\0'; /* text meta-event nultermination */ + } + } + else { + if (x->s_anapass) + post("unknown event type in midifile -- skip to end of track"); + goto endoftrack; + } + + return ((e->e_status = status) == MIFI_EVENT_META ? e->e_meta : status); + +endoftrack: + if (mifi_skipbytes(x, x->s_bytesleft) < 0) + return (MIFI_READ_FATAL); + return (MIFI_READ_SKIP); +} + +/* Gather statistics (nevents, ntracks, ntempi), pick track names, and + allocate the maps. To be called in the first pass of reading. +*/ +/* LATER consider optional reading of nonchannel events */ +int mifi_read_analyse(t_mifi_stream *x) +{ + t_mifi_event *evp = x->s_auxeve; + int evtype, result = MIFI_READ_FATAL; + int isnewtrack = 0; + int i; + char tnamebuf[MAXPDSTRING]; + t_symbol *tnamesym = 0; + t_squack *trp = 0; + + *tnamebuf = '\0'; + x->s_alltracks = x->s_ntracks = 0; + x->s_nevents = 0; + x->s_ntempi = 0; + + while ((evtype = mifi_read_event(x, evp)) >= MIFI_READ_SKIP) + { + if (evtype == MIFI_READ_SKIP) + continue; + if (x->s_newtrack) + { +#ifdef MIFI_VERBOSE + post("track %d", x->s_track); +#endif + isnewtrack = 1; + *tnamebuf = '\0'; + tnamesym = 0; /* set to nonzero for nonempty tracks only */ + } + if (MIFI_IS_CHANNEL(evtype)) + { + if (isnewtrack) + { + isnewtrack = 0; + x->s_alltracks++; + if (!(trp = squax_add(x))) + goto anafail; + if (*tnamebuf) + { + tnamesym = trp->tr_name = gensym(tnamebuf); +#ifdef MIFI_DEBUG + post("nonempty track name %s", tnamesym->s_name); +#endif + } + else tnamesym = trp->tr_name = &s_; + } + x->s_nevents++; + } + else if (evtype < 0x80) + { + mifi_event_printmeta(evp); + if (evtype == MIFI_META_TEMPO) + x->s_ntempi++; + else if (evtype == MIFI_META_TRACKNAME) + { + char *p1 = evp->e_data; + if (*p1 && + !*tnamebuf) /* take the first one */ + { + while (*p1 == ' ') p1++; + if (*p1) + { + char *p2 = evp->e_data + evp->e_length - 1; + while (p2 > p1 && *p2 == ' ') *p2-- = '\0'; + p2 = p1; + do if (*p2 == ' ' || *p2 == ',' || *p2 == ';') + *p2 = '-'; + while (*++p2); + if (tnamesym == &s_) + { /* trackname after channel-event */ + if (trp) /* redundant check */ + tnamesym = trp->tr_name = gensym(p1); + } + else strcpy(tnamebuf, p1); + } + } + } + } + } + if (evtype != MIFI_READ_EOF) + goto anafail; + + i = x->s_ntracks; + while (--i >= 0) + { + if (!x->s_track_name(i) || x->s_track_name(i) == &s_) + { + sprintf(tnamebuf, "%d-track", i); + x->s_track_name(i) = gensym(tnamebuf); + } + } + + /* now (re)allocate the buffers */ + if (squb_checksize(x->s_mytempi, + x->s_ntempi, sizeof(t_squmpo)) < x->s_ntempi) + goto anafail; + x->s_track_nevents(0) = 0; + x->s_track_nevents(x->s_ntracks) = x->s_nevents; /* guard point */ + + result = evtype; +anafail: + return (result); +} + +/* To be called in second pass of reading */ +/* LATER do not trust analysis: in case of inconsistency give up or checksize */ +int mifi_read_doit(t_mifi_stream *x) +{ + t_mifi_event *evp = x->s_auxeve; + t_squiter *it = x->s_myiter; + t_squiter_seekhook seekhook = squiter_seekhook(it); + t_squiter_incrhook incrhook = squiter_incrhook(it); + t_squiter_setevehook evehook = squiter_setevehook(it); + t_squiter_settimhook timhook = squiter_settimhook(it); + t_squiter_settarhook tarhook = squiter_settarhook(it); + int evtype, result = MIFI_READ_FATAL; + int nevents = x->s_nevents; /* three proxies... */ + int ntracks = x->s_ntracks; + int ntempi = x->s_ntempi; + int trackno = 0; + t_symbol *trackname = 0; + int isnewtrack = 0; + t_squmpo *tp = x->s_tempomap; + + if (!it || !seekhook(it, 0)) + goto readfailed; + + while ((evtype = mifi_read_event(x, evp)) >= MIFI_READ_SKIP) + { + if (evtype == MIFI_READ_SKIP) + continue; + if (x->s_newtrack) + isnewtrack = 1; + if (MIFI_IS_CHANNEL(evtype)) + { + int ret; + if (isnewtrack) + { + isnewtrack = 0; + trackname = x->s_track_name(trackno); + trackno++; + if (!trackname || trackname == &s_) + { + bug("mifi_read_doit: empty track name"); + trackname = gensym("bug-track"); + } + } + x->s_track_nevents(trackno)++; + if (ret = squiter_inrange(it)) + { + evehook(it, (t_squeve *)evp, &ret); + /* We store onset times instead of delta times, because: + 1) some deltas may represent delays since nonchannel events; + 2) we'll need onsets while merging the tracks. */ + if (ret) timhook(it, (t_float)x->s_time, &ret); + if (ret) tarhook(it, trackname, &ret); + } + if (ret) incrhook(it); + else + goto readfailed; + } + else if (evtype < 0x80) + { + if (evtype == MIFI_META_TEMPO) + { + tp->te_onset = x->s_time; + tp->te_value = x->s_tempo; + tp++; + } + } + } + if (evtype != MIFI_READ_EOF) + goto readfailed; + + result = evtype; +readfailed: + return (result); +} + +/* Open midifile for saving, write the header. May be used as t_mifi_stream + allocator (if x is a null pointer), to be freed by mifi_write_end() or + explicitly. + + Return value: null on error, else x if passed a valid pointer, else pointer + to allocated structure. +*/ +t_mifi_stream *mifi_write_start(t_mifi_stream *x, + const char *filename, const char *dirname) +{ + t_mifi_stream *result = x; + t_bifi bifi; + t_bifi *bp = &bifi; + t_mifi_header header; + + /* this must precede bifi_swap() calls */ + bifi_new(bp, (char *)&header, MIFI_HEADER_SIZE); + + if (x->s_format == 0) + { + if (x->s_ntracks != 1) + goto startfailure; /* LATER replace with a warning only? */ +#ifdef MIFI_VERBOSE + post("writing singletrack midifile %s", filename); +#endif + } +#ifdef MIFI_VERBOSE + else post("writing midifile %s (%d tracks)", filename, x->s_ntracks); +#endif + + strncpy(header.h_type, "MThd", 4); + header.h_length = bifi_swap4(MIFI_HEADERDATA_SIZE); + if (x) + { + if (!x->s_hdtracks || !x->s_nticks) + goto startfailure; + header.h_format = bifi_swap2(x->s_format); + header.h_ntracks = bifi_swap2(x->s_hdtracks); + if (x->s_nframes) + header.h_division = ((x->s_nframes << 8) | x->s_nticks) | 0x8000; + else + header.h_division = x->s_nticks & 0x7fff; + header.h_division = bifi_swap2(header.h_division); + } + else { + header.h_format = 0; + header.h_ntracks = bifi_swap2(1); + header.h_division = bifi_swap2(192); /* LATER parametrize this somehow */ + } + + if (!bifi_write_start(bp, filename, dirname)) + { + bifi_error_report(bp); + bifi_free(bp); + return (0); + } + + if (x) mifi_stream_reset(x); + else + { + if (!(result = mifi_stream_new())) + goto startfailure; + result->s_autoalloc = 1; + } + result->s_fp = bp->b_fp; + result->s_track = 0; + + return (result); +startfailure: + if (result && !x) mifi_stream_free(result); + bifi_free(bp); + return (0); +} + +/* Close midifile, free t_mifi_stream if it was allocated + by mifi_write_start(). */ +void mifi_write_end(t_mifi_stream *x) +{ + if (x->s_autoalloc) + { + /* LATER adjust ntracks field in a file header, but do so only if + a stream was autoallocated -- number of tracks must be known + before calling mifi_write_start() for a preexisting stream. */ + } + if (x->s_fp) fclose(x->s_fp); + if (x->s_autoalloc) mifi_stream_free(x); +} + +int mifi_write_start_track(t_mifi_stream *x) +{ + t_mifi_trackheader header; + /* LATER check if (x->s_track < x->s_hdtracks)... after some thinking */ + strncpy(header.h_type, "MTrk", 4); + header.h_length = 0; + x->s_trackid = x->s_track_id(x->s_track); + x->s_track++; + x->s_newtrack = 1; + x->s_status = x->s_channel = 0; + x->s_bytesleft = 0; + x->s_time = 0; + if (fwrite(&header, 1, + MIFI_TRACKHEADER_SIZE, x->s_fp) != MIFI_TRACKHEADER_SIZE) + { + post("unable to write midifile header"); + return (0); + } + return (1); +} + +/* append eot meta and update length field in a track header */ +int mifi_write_adjust_track(t_mifi_stream *x, uint32 eotdelay) +{ + t_mifi_event *evp = x->s_auxeve; + long skip; + uint32 length; + evp->e_delay = eotdelay; + evp->e_status = MIFI_EVENT_META; + evp->e_meta = MIFI_META_EOT; + evp->e_length = 0; + if (!mifi_write_event(x, evp)) + return (0); + skip = x->s_bytesleft + 4; + length = bifi_swap4(x->s_bytesleft); +#ifdef MIFI_DEBUG + post("adjusting track size to %d", x->s_bytesleft); +#endif + /* LATER add sanity check (compare to saved filepos) */ + if (skip > 4 && + fseek(x->s_fp, -skip, SEEK_CUR) < 0 || + fwrite(&length, 1, 4, x->s_fp) != 4 || + fseek(x->s_fp, 0, SEEK_END) < 0) + { + post("unable to adjust length field in midifile track header (length %d)", + x->s_bytesleft); + return (0); + } + return (1); +} + +/* LATER analyse shrinking effect caused by truncation */ +int mifi_write_event(t_mifi_stream *x, t_mifi_event *e) +{ + uchar buf[3], *ptr = buf; + size_t size = mifi_writevarlen(x, e->e_delay); + if (!size) + return (0); + x->s_bytesleft += size; + if (MIFI_IS_CHANNEL(e->e_status)) + { + if ((*ptr = e->e_status | e->e_channel) == x->s_status) + size = 1; + else { + x->s_status = *ptr++; + size = 2; + } + *ptr++ = e->e_data[0]; + if (!MIFI_ONE_DATABYTE(e->e_status)) + { + *ptr = e->e_data[1]; + size++; + } + ptr = buf; + } + else if (e->e_status == MIFI_EVENT_META) + { + x->s_status = 0; /* sysex and meta-events cancel any running status */ + buf[0] = e->e_status; + buf[1] = e->e_meta; + if (fwrite(buf, 1, 2, x->s_fp) != 2) + return (0); + x->s_bytesleft += 2; + size = mifi_writevarlen(x, (uint32)(e->e_length)); + if (!size) + return (0); + x->s_bytesleft += size; + size = e->e_length; + ptr = e->e_data; + } + else return (0); + if (fwrite(ptr, 1, size, x->s_fp) != size) + return (0); + x->s_bytesleft += size; + return (1); +} diff --git a/shared/common/mifi.h b/shared/common/mifi.h new file mode 100644 index 0000000..3893616 --- /dev/null +++ b/shared/common/mifi.h @@ -0,0 +1,84 @@ +/* Copyright (c) 2001-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* reading/writing midifiles, a prototype version */ + +#ifndef __MIFI_H__ +#define __MIFI_H__ + +/* event types, as returned by mifi_read_event() */ +#define MIFI_READ_FATAL -3 /* unexpected eof, error in last track, or file error */ +#define MIFI_READ_EOF -2 /* regular eof */ +#define MIFI_READ_SKIP -1 /* error and successful skip to the next track */ +#define MIFI_META_SEQNUM 0 +#define MIFI_META_TEXT 1 +#define MIFI_META_COPYRIGHT 2 +#define MIFI_META_TRACKNAME 3 +#define MIFI_META_INSTRUMENT 4 +#define MIFI_META_LYRIC 5 +#define MIFI_META_MARKER 6 +#define MIFI_META_CUE 7 +#define MIFI_META_MAXPRINTABLE 15 /* 1..15 are various text meta-events */ +#define MIFI_META_CHANNEL 0x20 /* channel prefix */ +#define MIFI_META_EOT 0x2f /* end of track */ +#define MIFI_META_TEMPO 0x51 +#define MIFI_META_SMPTE 0x54 /* SMPTE offset */ +#define MIFI_META_TIMESIG 0x58 /* time signature */ +#define MIFI_META_KEYSIG 0x59 /* key signature */ +/* ...channel status codes go here, too obvious to #define... */ +#define MIFI_SYSEX_FIRST 0xf0 +#define MIFI_SYSEX_NEXT 0xf7 +/* this code is not returned as an event type, but in e_status of t_mifi_event */ +#define MIFI_EVENT_META 0xff + +/* true if one of channel messages */ +#define MIFI_IS_CHANNEL(status) (((status) & 0x80) && (status) < 0xf0) +/* true if one of the two shorter channel messages */ +#define MIFI_ONE_DATABYTE(status) (((status) & 0xe0) == 0xc0) + +/* derived from t_squeve */ +typedef struct _mifi_event +{ + uint32 e_length; + uchar *e_data; + size_t e_bufsize; + uint32 e_delay; + uchar e_status; + uchar e_channel; + uchar e_meta; /* meta-event type */ +} t_mifi_event; + +/* This structure holds midi data stream properties, i.e. both the info stored + in midifile header, and the current state according to position in a stream. */ +/* LATER clean up t_sq and derive t_mifi_stream */ +typedef struct _sq t_mifi_stream; + +/* prototypes of public interface routines */ + +t_mifi_event *mifi_event_new(void); +void mifi_event_free(t_mifi_event *e); +int mifi_event_settext(t_mifi_event *e, int type, char *text); +void mifi_event_printmeta(t_mifi_event *e); + +t_mifi_stream *mifi_stream_new(void); +void mifi_stream_reset(t_mifi_stream *x); +void mifi_stream_free(t_mifi_stream *x); + +t_mifi_stream *mifi_read_start(t_mifi_stream *x, + const char *filename, const char *dirname, + int complain); +int mifi_read_restart(t_mifi_stream *x); +void mifi_read_end(t_mifi_stream *x); +int mifi_read_event(t_mifi_stream *x, t_mifi_event *e); +int mifi_read_analyse(t_mifi_stream *stp); +int mifi_read_doit(t_mifi_stream *stp); + +t_mifi_stream *mifi_write_start(t_mifi_stream *x, + const char *filename, const char *dirname); +void mifi_write_end(t_mifi_stream *x); +int mifi_write_start_track(t_mifi_stream *x); +int mifi_write_adjust_track(t_mifi_stream *x, uint32 eotdelay); +int mifi_write_event(t_mifi_stream *x, t_mifi_event *e); + +#endif diff --git a/shared/common/port.c b/shared/common/port.c new file mode 100644 index 0000000..f1471bf --- /dev/null +++ b/shared/common/port.c @@ -0,0 +1,612 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* CHECKME inlet/outlet vs inlet~/outlet~ */ +/* LATER think about abstractions */ +/* LATER sort out escaping rules (also revisit binport.c) */ +/* LATER quoting */ +/* LATER resolve object names (preserve connections of unknown dummies?) */ + +#ifdef UNIX +#include <unistd.h> +#endif +#ifdef NT +#include <io.h> +#endif +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "common/loud.h" +#include "common/grow.h" +#include "common/binport.h" +#include "common/port.h" + +#define PORT_INISTACK 256 /* LATER rethink */ +#define PORT_INISIZE 512 /* LATER rethink */ + +enum { PORT_OK, + PORT_NEXT, /* next line, please */ + PORT_UNKNOWN, PORT_CORRUPT, PORT_FATAL }; + +#define PORT_DEFFONTSIZE 10. +#define PORT_XSTRETCH 1.25 +#define PORT_YSTRETCH 1.1 +#define PORT_WSTRETCH 1.25 + +typedef struct _port +{ + t_binbuf *x_oldbb; + t_binbuf *x_newbb; + int x_nobj; + int x_inatoms; + t_atom *x_inmess; + int x_outsize; + int x_outatoms; + t_atom *x_outmess; + t_atom x_outini[PORT_INISIZE]; + int x_stacksize; + int x_stackdepth; + int *x_stack; + int x_stackini[PORT_INISTACK]; +} t_port; + +static t_float port_floatarg(t_port *x, int ndx) +{ + if (ndx < x->x_inatoms) + { + t_atom *av = &x->x_inmess[ndx]; + return (av->a_type == A_FLOAT ? av->a_w.w_float : 0); + } + else return (0); +} + +static t_symbol *port_symbolarg(t_port *x, int ndx) +{ + if (ndx < x->x_inatoms) + { + t_atom *av = &x->x_inmess[ndx]; + return (av->a_type == A_SYMBOL ? av->a_w.w_symbol : &s_); + } + else return (&s_); +} + +static int port_xstretch(float f) +{ + return ((int)(f * PORT_XSTRETCH + 0.5)); +} + +static int port_ystretch(float f) +{ + return ((int)(f * PORT_YSTRETCH + 0.5)); +} + +static int port_wstretch(float f) +{ + return ((int)(f * PORT_WSTRETCH + 0.5)); +} + +static t_float port_xarg(t_port *x, int ndx) +{ + return ((t_float)port_xstretch(port_floatarg(x, ndx))); +} + +static t_float port_yarg(t_port *x, int ndx) +{ + return ((t_float)port_ystretch(port_floatarg(x, ndx))); +} + +static t_float port_widtharg(t_port *x, int ndx) +{ + return ((t_float)port_wstretch(port_floatarg(x, ndx))); +} + +static void port_setxy(t_port *x, int ndx, t_atom *ap) +{ + float f = port_xarg(x, ndx); + SETFLOAT(ap, f); + ndx++; ap++; + f = port_yarg(x, ndx); + SETFLOAT(ap, f); +} + +static int import_obj(t_port *x, char *name) +{ + int ndx = (x->x_inmess[1].a_w.w_symbol == gensym("user") ? 3 : 2); + binbuf_addv(x->x_newbb, "ssffs;", + gensym("#X"), gensym("obj"), + port_xarg(x, ndx), port_yarg(x, ndx + 1), + (name ? gensym(name) : + x->x_inmess[ndx == 2 ? 6 : 2].a_w.w_symbol)); + x->x_nobj++; + return (PORT_NEXT); +} + +static int import_objarg(t_port *x, char *name) +{ + int ndx = (x->x_inmess[1].a_w.w_symbol == gensym("user") ? 3 : 2); + if (x->x_inatoms > 6) + { + t_atom *in = x->x_inmess + ndx + 4; + t_atom *out = x->x_outmess; + SETSYMBOL(out, gensym("#X")); out++; + SETSYMBOL(out, gensym("obj")); out++; + port_setxy(x, ndx, out); out++; out++; + if (name) + { + SETSYMBOL(out, gensym(name)); out++; + if (ndx == 2) in++; + } + else *out++ = (ndx == 2 ? *in++ : x->x_inmess[2]); + for (ndx = 7; ndx < x->x_inatoms; ndx++) + *out++ = *in++; + SETSEMI(out); + binbuf_add(x->x_newbb, x->x_inatoms - 1, x->x_outmess); + x->x_nobj++; + return (PORT_NEXT); + } + else return (PORT_CORRUPT); +} + +static int imaction_vpatcher(t_port *x, char *arg) +{ + if (x->x_stackdepth >= x->x_stacksize) + { + int rqsz = x->x_stackdepth + 1; + int sz = rqsz; + x->x_stack = grow_withdata(&rqsz, &x->x_stackdepth, + &x->x_stacksize, x->x_stack, + PORT_INISTACK, x->x_stackini, + sizeof(*x->x_stack)); + if (rqsz != sz) + { + post("too many embedded patches"); + return (PORT_FATAL); + } + } + x->x_stack[x->x_stackdepth++] = x->x_nobj; + x->x_nobj = 0; + binbuf_addv(x->x_newbb, "ssfffff;", + gensym("#N"), gensym("canvas"), + port_xarg(x, 2), port_yarg(x, 3), + (float)port_xstretch(port_floatarg(x, 4) - port_floatarg(x, 2)), + (float)port_ystretch(port_floatarg(x, 5) - port_floatarg(x, 3)), + PORT_DEFFONTSIZE); + return (PORT_NEXT); +} + +static int imaction_patcher(t_port *x, char *arg) +{ + binbuf_addv(x->x_newbb, "ssffss;", + gensym("#X"), gensym("restore"), + port_xarg(x, 2), port_yarg(x, 3), + gensym("pd"), port_symbolarg(x, 7)); + if (x->x_stackdepth) /* LATER consider returning PORT_FATAL otherwise */ + x->x_stackdepth--; + x->x_nobj = x->x_stack[x->x_stackdepth]; + x->x_nobj++; + return (PORT_NEXT); +} + +static int imaction_trigger(t_port *x, char *arg) +{ + int i; + for (i = 7; i < x->x_inatoms; i++) + if (x->x_inmess[i].a_type == A_SYMBOL && + x->x_inmess[i].a_w.w_symbol == gensym("i")) + x->x_inmess[i].a_w.w_symbol = gensym("f"); + return (PORT_OK); +} + +static int imaction_scope(t_port *x, char *name) +{ + if (x->x_inatoms > 6) + { + t_atom *in = x->x_inmess + 7; + t_atom *out = x->x_outmess; + int i, xpix, ypix; + SETSYMBOL(out, gensym("#X")); out++; + SETSYMBOL(out, gensym("obj")); out++; + port_setxy(x, 3, out); + xpix = (int)out++->a_w.w_float; + ypix = (int)out++->a_w.w_float; + if (name) + { + SETSYMBOL(out, gensym(name)); out++; + } + else *out++ = x->x_inmess[2]; + port_setxy(x, 5, out); + out++->a_w.w_float -= xpix; + out++->a_w.w_float -= ypix; + for (i = 7; i < x->x_inatoms; i++) + *out++ = *in++; + SETSEMI(out); + binbuf_add(x->x_newbb, x->x_inatoms + 1, x->x_outmess); + x->x_nobj++; + return (PORT_NEXT); + } + else return (PORT_CORRUPT); +} + +/* width fontsize fontfamily encoding fontprops red green blue text... */ +static int imaction_comment(t_port *x, char *arg) +{ + int outatoms; + SETSYMBOL(x->x_outmess, gensym("#X")); + SETSYMBOL(x->x_outmess + 1, gensym("obj")); + port_setxy(x, 2, x->x_outmess + 2); + SETSYMBOL(x->x_outmess + 4, gensym("comment")); + if (x->x_inatoms > 5) + { + int i, fontsize, fontprops; + float width = port_widtharg(x, 4); + t_atom *ap = x->x_inmess + 5; + SETFLOAT(x->x_outmess + 5, width); + if (ap->a_type == A_FLOAT) + { + fontsize = ((int)ap->a_w.w_float) & 0x0ff; + fontprops = ((int)ap->a_w.w_float) >> 8; + } + else fontsize = 10, fontprops = 0; + SETFLOAT(x->x_outmess + 6, fontsize); + SETSYMBOL(x->x_outmess + 7, gensym("helvetica")); + SETSYMBOL(x->x_outmess + 8, gensym("?")); + SETFLOAT(x->x_outmess + 9, fontprops); + SETFLOAT(x->x_outmess + 10, 0); + SETFLOAT(x->x_outmess + 11, 0); + SETFLOAT(x->x_outmess + 12, 0); + outatoms = x->x_inatoms + 7; + for (i = 13; i < outatoms ; i++) + x->x_outmess[i] = x->x_inmess[i - 7]; + } + else outatoms = 5; + SETSEMI(x->x_outmess + outatoms); + binbuf_add(x->x_newbb, outatoms + 1, x->x_outmess); + x->x_nobj++; + return (PORT_NEXT); +} + +static int imaction_message(t_port *x, char *arg) +{ + int i; + SETSYMBOL(x->x_outmess, gensym("#X")); + SETSYMBOL(x->x_outmess + 1, gensym("msg")); + port_setxy(x, 2, x->x_outmess + 2); + for (i = 6; i < x->x_inatoms; i++) + x->x_outmess[i-2] = x->x_inmess[i]; + SETSEMI(x->x_outmess + x->x_inatoms - 2); + binbuf_add(x->x_newbb, x->x_inatoms - 1, x->x_outmess); + x->x_nobj++; + return (PORT_NEXT); +} + +/* FIXME this is no longer true */ +static int imaction_inlet(t_port *x, char *arg) +{ + return (import_obj(x, (port_floatarg(x, 5) ? "inlet~" : "inlet"))); +} + +/* FIXME this is no longer true */ +static int imaction_outlet(t_port *x, char *arg) +{ + return (import_obj(x, (port_floatarg(x, 5) ? "outlet~" : "outlet"))); +} + +static int imaction_number(t_port *x, char *arg) +{ + binbuf_addv(x->x_newbb, "ssff;", + gensym("#X"), gensym("floatatom"), + port_xarg(x, 2), port_yarg(x, 3)); + x->x_nobj++; + return (PORT_NEXT); +} + +static int imaction_connect(t_port *x, char *arg) +{ + binbuf_addv(x->x_newbb, "ssffff;", + gensym("#X"), gensym("connect"), + x->x_nobj - port_floatarg(x, 2) - 1, + port_floatarg(x, 3), + x->x_nobj - port_floatarg(x, 4) - 1, + port_floatarg(x, 5)); + return (PORT_NEXT); +} + +typedef int (*t_portaction)(t_port *, char *arg); + +typedef struct _portslot +{ + char *s_name; + int s_index; + t_portaction s_action; + char *s_actionarg; + struct _portnode *s_subtree; + t_symbol *s_symbol; +} t_portslot; + +typedef struct _portnode /* a parser's symbol definition, sort of... */ +{ + t_portslot *n_table; + int n_nslots; +} t_portnode; + +#define PORT_NSLOTS(slots) (sizeof(slots)/sizeof(*(slots))) + +static t_portslot imslots__N[] = +{ + { "vpatcher", 1, imaction_vpatcher, 0, 0, 0 } +}; +static t_portnode imnode__N = { imslots__N, PORT_NSLOTS(imslots__N) }; + +static t_portslot imslots_newobj[] = +{ + { "patcher", 6, imaction_patcher, 0, 0, 0 }, + { "p", 6, imaction_patcher, 0, 0, 0 }, + /* state is embedded in #N vtable...; #T set...; */ + { "table", 6, import_obj, "Table", 0, 0 } +}; +static t_portnode imnode_newobj = { imslots_newobj, + PORT_NSLOTS(imslots_newobj) }; + +/* LATER consider merging newobj and newex */ +static t_portslot imslots_newex[] = +{ + { "append", 6, import_objarg, "Append", 0, 0 }, + { "biquad~", 6, import_objarg, "Biquad~", 0, 0 }, + { "change", 6, import_objarg, "Change", 0, 0 }, + { "clip", 6, import_objarg, "Clip", 0, 0 }, + { "clip~", 6, import_objarg, "Clip~", 0, 0 }, + { "key", 6, import_obj, "Key", 0, 0 }, + { "keyup", 6, import_obj, "Keyup", 0, 0 }, + { "line", 6, import_objarg, "Line", 0, 0 }, + { "line~", 6, import_objarg, "Line~", 0, 0 }, + { "poly", 6, import_objarg, "Poly", 0, 0 }, + { "snapshot~", 6, import_objarg, "Snapshot~", 0, 0 }, + { "trigger", 6, imaction_trigger, 0, 0, 0 }, + { "t", 6, imaction_trigger, 0, 0, 0 } +}; +static t_portnode imnode_newex = { imslots_newex, + PORT_NSLOTS(imslots_newex) }; + +static t_portslot imslots_user[] = +{ + { "GSwitch", 2, import_objarg, "Gswitch", 0, 0 }, + { "GSwitch2", 2, import_objarg, "Ggate", 0, 0 }, + { "number~", 2, import_obj, 0, 0, 0 }, + { "scope~", 2, imaction_scope, "Scope~", 0, 0 }, + { "uslider", 2, import_obj, "vsl", 0, 0 } /* LATER range and offset */ +}; +static t_portnode imnode_user = { imslots_user, + PORT_NSLOTS(imslots_user) }; + +static t_portslot imslots__P[] = +{ + { "comment", 1, imaction_comment, 0, 0, 0 }, + { "message", 1, imaction_message, 0, 0, 0 }, + { "newobj", 1, import_objarg, 0, &imnode_newobj, 0 }, + { "newex", 1, import_objarg, 0, &imnode_newex, 0 }, + { "inlet", 1, imaction_inlet, 0, 0, 0 }, + { "inlet~", 1, imaction_inlet, 0, 0, 0 }, + { "outlet", 1, imaction_outlet, 0, 0, 0 }, + { "outlet~", 1, imaction_outlet, 0, 0, 0 }, + { "number", 1, imaction_number, 0, 0, 0 }, + { "flonum", 1, imaction_number, 0, 0, 0 }, + { "button", 1, import_obj, "bng", 0, 0 }, + { "slider" , 1, import_obj, "vsl", 0, 0 }, /* LATER range and offset */ + { "hslider", 1, import_obj, "hsl", 0, 0 }, /* LATER range and offset */ + { "toggle", 1, import_obj, "tgl", 0, 0 }, + { "user", 1, import_objarg, 0, &imnode_user, 0 }, + /* state is embedded in #N vpreset <nslots>; #X append... */ + { "preset", 1, import_obj, "preset", 0, 0 }, + /* an object created from the "Paste Picture" menu, + state is embedded in #N picture; #K...; */ + { "vpicture", 1, import_obj, "vpicture", 0, 0 }, + { "connect", 1, imaction_connect, 0, 0, 0 }, + { "fasten", 1, imaction_connect, 0, 0, 0 } +}; +static t_portnode imnode__P = { imslots__P, PORT_NSLOTS(imslots__P) }; + +static t_portslot imslots_[] = +{ + { "#N", 0, 0, 0, &imnode__N, 0 }, + { "#P", 0, 0, 0, &imnode__P, 0 } +}; +static t_portnode imnode_ = { imslots_, PORT_NSLOTS(imslots_) }; + +static int port_doit(t_port *x, t_portnode *node) +{ + int nslots = node->n_nslots; + if (nslots > 0) + { + t_portslot *slot = node->n_table; + t_symbol *s = port_symbolarg(x, slot->s_index); + while (nslots--) + { + if (slot->s_symbol == s) + { + if (slot->s_subtree) + { + int nobj = x->x_nobj; + int result = port_doit(x, slot->s_subtree); + if (result == PORT_FATAL || result == PORT_CORRUPT || + result == PORT_NEXT) + return (result); + } + if (slot->s_action) + return (slot->s_action(x, slot->s_actionarg)); + else + return (PORT_OK); /* LATER rethink */ + } + slot++; + } + } + else bug("port_doit"); + return (PORT_UNKNOWN); +} + +static void port_dochecksetup(t_portnode *node) +{ + t_portslot *slots = node->n_table; + int i, nslots = node->n_nslots; + for (i = 0; i < nslots; i++) + { + t_portnode *subtree = slots[i].s_subtree; + slots[i].s_symbol = gensym(slots[i].s_name); + if (subtree) + port_dochecksetup(subtree); + } +} + +static void port_checksetup(void) +{ + static int done = 0; + if (!done) + { + port_dochecksetup(&imnode_); + done = 1; + } +} + +static t_port *port_new(void) +{ + t_port *x = (t_port *)getbytes(sizeof(*x)); + x->x_oldbb = binbuf_new(); + x->x_outsize = PORT_INISIZE; + x->x_outatoms = 0; + x->x_outmess = x->x_outini; + x->x_stacksize = PORT_INISTACK; + x->x_stackdepth = 0; + x->x_stack = x->x_stackini; + return (x); +} + +static void port_free(t_port *x) +{ + if (x->x_outmess != x->x_outini) + freebytes(x->x_outmess, x->x_outsize * sizeof(*x->x_outmess)); + if (x->x_stack != x->x_stackini) + freebytes(x->x_stack, x->x_stacksize * sizeof(*x->x_stack)); + freebytes(x, sizeof(*x)); +} + +static int import_binbuf(t_port *x) +{ + t_atom *av = binbuf_getvec(x->x_oldbb); + int ac = binbuf_getnatom(x->x_oldbb); + int startmess, endmess; + x->x_newbb = binbuf_new(); + for (startmess = 0; startmess < ac; startmess = endmess + 1) + { + t_atom *mess = av + startmess, *ap; + int i; + for (endmess = startmess, ap = mess; + ap->a_type != A_SEMI; endmess++, ap++) + if (endmess == ac) + return (PORT_CORRUPT); /* no final semi */ + if (endmess == startmess || endmess == startmess + 1 + || mess->a_type != A_SYMBOL || mess[1].a_type != A_SYMBOL) + { + startmess = endmess + 1; + continue; + } + if (mess[1].a_w.w_symbol == gensym("hidden")) + { + t_symbol *sel = mess[1].a_w.w_symbol; + mess[1].a_w.w_symbol = mess->a_w.w_symbol; + startmess++; + mess++; + if (endmess == startmess + 1 || mess[1].a_type != A_SYMBOL) + { + startmess = endmess + 1; + continue; + } + } + x->x_inatoms = endmess - startmess; + x->x_inmess = mess; + if ((i = x->x_inatoms + 16) > x->x_outsize) /* LATER rethink */ + { + int sz = i; + x->x_outmess = grow_nodata(&sz, &x->x_outsize, x->x_outmess, + PORT_INISIZE, x->x_outini, + sizeof(*x->x_outmess)); + if (sz != i) + { + startmess = endmess + 1; + continue; /* LATER rethink */ + } + } + + /* dollar signs in file translate to symbols, + LATER rethink, also #-signs */ + for (i = 0, ap = x->x_inmess; i < x->x_inatoms; i++, ap++) + { + if (ap->a_type == A_DOLLAR) + { + char buf[100]; + sprintf(buf, "$%d", ap->a_w.w_index); + SETSYMBOL(ap, gensym(buf)); + } + else if (ap->a_type == A_DOLLSYM) + { + char buf[100]; + sprintf(buf, "$%s", ap->a_w.w_symbol->s_name); + SETSYMBOL(ap, gensym(buf)); + } + } + if (port_doit(x, &imnode_) == PORT_FATAL) + return (PORT_FATAL); + } + return (PORT_OK); +} + +void import_max(char *fn, char *dir) +{ + t_port *x; + int failure, fd, ftype; + char buf[MAXPDSTRING], *bufp; + t_pd *stackp = 0; + int dspstate = canvas_suspend_dsp(); + port_checksetup(); + if ((fd = open_via_path(dir, fn, "", buf, &bufp, MAXPDSTRING, 0)) < 0) + { + loud_error(0, "%s: can't open", fn); + return; + } + else close (fd); + + x = port_new(); + glob_setfilename(0, gensym(bufp), gensym(buf)); + ftype = binport_read(x->x_oldbb, bufp, buf); + if (ftype == BINPORT_MAXTEXT || ftype == BINPORT_PDFILE) + failure = binbuf_read(x->x_oldbb, bufp, buf, 0); + else + failure = (ftype != BINPORT_OK); /* LATER rethink */ + if (failure) + { + perror(fn); /* FIXME */ + binbuf_free(x->x_oldbb); + } + else + { + if (ftype == BINPORT_PDFILE) x->x_newbb = x->x_oldbb; + else + { + import_binbuf(x); + binbuf_free(x->x_oldbb); +#if 1 + binbuf_write(x->x_newbb, "import-result.pd", "", 0); +#endif + } + binbuf_eval(x->x_newbb, 0, 0, 0); + binbuf_free(x->x_newbb); + } + port_free(x); + + glob_setfilename(0, &s_, &s_); + canvas_resume_dsp(dspstate); + while ((stackp != s__X.s_thing) && (stackp = s__X.s_thing)) + vmess(stackp, gensym("pop"), "i", 1); +#if 0 /* LATER */ + pd_doloadbang(); +#endif +} diff --git a/shared/common/port.h b/shared/common/port.h new file mode 100644 index 0000000..5d2c118 --- /dev/null +++ b/shared/common/port.h @@ -0,0 +1,10 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __PORT_H__ +#define __PORT_H__ + +void import_max(char *fn, char *dir); + +#endif diff --git a/shared/common/rand.c b/shared/common/rand.c new file mode 100644 index 0000000..37dcf62 --- /dev/null +++ b/shared/common/rand.c @@ -0,0 +1,61 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <time.h> +#include "m_pd.h" +EXTERN double sys_getrealtime(void); /* used to be in m_imp.h */ +#include "common/rand.h" + +/* borrowed from x_misc.c, LATER rethink */ +void rand_seed(unsigned int *statep, unsigned int seed) +{ + if (seed) *statep = (seed & 0x7fffffff); + else + { + /* LATER consider using time elapsed from system startup, + (or login -- in linux we might call getutent) */ + static unsigned int failsafe = 1489853723; + static int shift = 0; + static unsigned int lastticks = 0; + /* LATER rethink -- it might fail on faster machine than mine + (but does it matter?) */ + unsigned int newticks = (unsigned int)(sys_getrealtime() * 1000000.); + if (newticks == lastticks) + { + failsafe = failsafe * 435898247 + 938284287; + *statep = (failsafe & 0x7fffffff); +#ifdef RAND_DEBUG + post("rand_seed failed (newticks %d)", newticks); +#endif + } + else + { + if (!shift) + shift = (int)time(0); /* LATER deal with error return (-1) */ + *statep = ((newticks + shift) & 0x7fffffff); +#if 0 + post("rand_seed: newticks %d, shift %d", newticks, shift); +#endif + } + lastticks = newticks; + } +} + +/* borrowed from x_misc.c, LATER rethink */ +int rand_int(unsigned int *statep, int range) +{ + int result; + *statep = *statep * 472940017 + 832416023; + result = ((double)range) * ((double)*statep) * (1./4294967296.); + return (result < range ? result : range - 1); +} + +/* borrowed from d_osc.c, LATER rethink */ +float rand_float(unsigned int *statep) +{ + float result = ((float)((*statep & 0x7fffffff) - 0x40000000)) + * (float)(1.0 / 0x40000000); + *statep = *statep * 435898247 + 382842987; + return (result); +} diff --git a/shared/common/rand.h b/shared/common/rand.h new file mode 100644 index 0000000..75350d2 --- /dev/null +++ b/shared/common/rand.h @@ -0,0 +1,14 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __RAND_H__ +#define __RAND_H__ + +#define RAND_DEBUG + +void rand_seed(unsigned int *statep, unsigned int seed); +int rand_int(unsigned int *statep, int range); +float rand_float(unsigned int *statep); + +#endif diff --git a/shared/common/sq.c b/shared/common/sq.c new file mode 100644 index 0000000..d7b1ea5 --- /dev/null +++ b/shared/common/sq.c @@ -0,0 +1,371 @@ +/* Copyright (c) 2001-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* squeak and squeal: sequencing utilities, a prototype version + (the main, 'sq' part of the library) */ + +#include <stdlib.h> +#include <stdio.h> +#include "m_pd.h" +#include "shared.h" +#include "common/sq.h" + +#if 1 +#define SQ_VERBOSE +#if 0 +#define SQ_DEBUG +#endif +#endif + +/* #define SQUMPI_IGNORE */ + +#define SQUB_NALLOC 32 +#define SQUMPI_NALLOC (32 * sizeof(t_squmpo)) +#define SQUAX_NALLOC (32 * sizeof(t_squack)) + +#define SQUMPI_DEFAULT 500000 /* 120 bpm in microseconds per beat */ + +/* Arguments reqcount and elsize as in calloc, returns count */ +size_t squb_checksize(void *buf, size_t reqcount, size_t elsize) +{ + t_squb *x = buf; + size_t reqsize = reqcount * elsize; + size_t newsize = x->b_bufsize; + while (newsize < reqsize) newsize *= 2; + if (newsize == x->b_bufsize) + return (newsize); +#ifdef SQ_DEBUG + post("need to resize buffer %x from %d to %d (requested size %d)", + (int)x, x->b_bufsize, newsize, reqsize); +#endif + if (!(x->b_data = resizebytes(x->b_data, x->b_bufsize, newsize)) && + /* rather hopeless... */ + !(x->b_data = getbytes(newsize = SQUB_NALLOC * elsize))) + newsize = 0; + return ((x->b_bufsize = newsize) / elsize); /* LATER do it right */ +} + +/* generic event */ + +/* tempo map */ + +/* comparison function used by qsort */ +static int squmpi_compare(const void *tp1, const void *tp2) +{ + return (((t_squmpo *)tp1)->te_onset > ((t_squmpo *)tp2)->te_onset ? 1 : -1); +} + +void squmpi_sort(t_sq *x) +{ + int i; + t_squmpo *tp; + qsort(x->s_tempomap, x->s_ntempi, sizeof(t_squmpo), squmpi_compare); +#if defined SQ_VERBOSE && ! defined SQ_DEBUG + for (i = x->s_ntempi, tp = x->s_tempomap; i > 0 ; i--, tp++) + post("tempo %d at %d", tp->te_value, (int)tp->te_onset); +#endif +} + +t_squmpo *squmpi_add(t_sq *x) +{ + size_t count = x->s_ntempi + 1; + t_squmpo *tep; + if (squb_checksize(x->s_mytempi, count, sizeof(t_squmpo)) < count) + return (0); + tep = x->s_tempomap + x->s_ntempi++; + squmpo_reset(tep); + return (tep); +} + +void squmpo_reset(t_squmpo *x) +{ + x->te_onset = 0; + x->te_value = SQUMPI_DEFAULT; +} + +/* track map */ + +t_squack *squax_add(t_sq *x) +{ + size_t count = x->s_ntracks + 2; /* guard point */ + t_squack *trp; + if (squb_checksize(x->s_mytracks, count, sizeof(t_squack)) < count) + return (0); + trp = x->s_trackmap + x->s_ntracks++; + squack_reset(trp); + return (trp); +} + +void squack_reset(t_squack *x) +{ + x->tr_id = 0; /* this is no-id */ + x->tr_nevents = 0; + x->tr_name = 0; + x->tr_head = 0; +} + +/* generic iterator */ + +void *squiter_new(t_sq *x) +{ + if (x->s_myiter = getbytes(sizeof(*x->s_myiter))) + { + } + return (x->s_myiter); +} + +/* routines to access iterator hooks (setting hooks is explicit only) */ +t_squiter_seekhook squiter_seekhook(t_squiter *x) +{ + return (x ? (t_squiter_seekhook)x->i_hooks[SQUITER_SEEKHOOK] : 0); +} + +t_squiter_incrhook squiter_incrhook(t_squiter *x) +{ + return (x ? (t_squiter_incrhook)x->i_hooks[SQUITER_INCRHOOK] : 0); +} + +t_squiter_getevehook squiter_getevehook(t_squiter *x) +{ + return (x ? (t_squiter_getevehook)x->i_hooks[SQUITER_GETEVEHOOK] : 0); +} + +t_squiter_setevehook squiter_setevehook(t_squiter *x) +{ + return (x ? (t_squiter_setevehook)x->i_hooks[SQUITER_SETEVEHOOK] : 0); +} + +t_squiter_gettimhook squiter_gettimhook(t_squiter *x) +{ + return (x ? (t_squiter_gettimhook)x->i_hooks[SQUITER_GETTIMHOOK] : 0); +} + +t_squiter_settimhook squiter_settimhook(t_squiter *x) +{ + return (x ? (t_squiter_settimhook)x->i_hooks[SQUITER_SETTIMHOOK] : 0); +} + +t_squiter_gettarhook squiter_gettarhook(t_squiter *x) +{ + return (x ? (t_squiter_gettarhook)x->i_hooks[SQUITER_GETTARHOOK] : 0); +} + +t_squiter_settarhook squiter_settarhook(t_squiter *x) +{ + return (x ? (t_squiter_settarhook)x->i_hooks[SQUITER_SETTARHOOK] : 0); +} + +/* time conversion */ + +/* Compute reusable coefficient, rather then repeatedly apply the formula. + For smpte time: + d msecs == (d / 1000.) secs == ((d * nframes * nticks) / 1000.) ticks + or for metrical time: + d msecs == (d * 1000.) usecs == ((d * 1000.) / tempo) beats + == ((d * nticks * 1000.) / tempo) ticks +*/ +/* LATER ntsc */ +float sq_ticks2msecs(t_sq *x, uint32 tempo) +{ + if (x->s_nframes) + return (1000. / (x->s_nframes * x->s_nticks)); + if (tempo <= 0) + tempo = x->s_tempo; + if (tempo <= 0) + tempo = SQUMPI_DEFAULT; + return (tempo / (x->s_nticks * 1000.)); +} + +float sq_msecs2ticks(t_sq *x, uint32 tempo) +{ + if (x->s_nframes) + return (((x->s_nframes * x->s_nticks) / 1000.)); + if (!tempo) + tempo = x->s_tempo; + if (!tempo) + tempo = SQUMPI_DEFAULT; + return ((x->s_nticks * 1000.) / tempo); +} + +/* transform onset ticks into delta msecs */ +void sq_fold_time(t_sq *x) +{ + t_squiter *it = x->s_myiter; + t_squiter_seekhook seekhook = squiter_seekhook(it); + t_squiter_incrhook incrhook = squiter_incrhook(it); + t_squiter_gettimhook gethook = squiter_gettimhook(it); + t_squiter_settimhook sethook = squiter_settimhook(it); + int i, ret, nevents = x->s_nevents; + + if (!it || !seekhook(it, 0)) + return; + if (x->s_nframes) + { + float coef = sq_ticks2msecs(x, 0); + t_float lasttime = 0; + for (i = 0; i < nevents; i++) + { + if (ret = squiter_inrange(it)) + { + t_float thistime = gethook(it, &ret) * coef; + /* back to delta time */ + if (ret) sethook(it, thistime - lasttime, &ret); + lasttime = thistime; + } + if (ret) incrhook(it); + else + { + post("sequence folding error: bad iterator"); + break; + } + } + } + else /* apply tempomap */ + { + float coef = sq_ticks2msecs(x, SQUMPI_DEFAULT); + int ntempi = x->s_ntempi; + t_float lasttime = 0, thistime = 0; + t_float temposince = 0; + t_float tempoonset = 0; + int tempondx = 0; + for (i = 0; i < nevents; i++) + { + if (ret = squiter_inrange(it)) + { + t_float thisonset = gethook(it, &ret); + t_float nexttempoonset; +#ifdef SQUMPI_IGNORE + thistime = thisonset * coef; +#else + while (tempondx < ntempi /* LATER consider using guard point */ + && (nexttempoonset = x->s_tempo_onset(tempondx)) + < thisonset) + { + temposince += (nexttempoonset - tempoonset) * coef; + tempoonset = nexttempoonset; + coef = sq_ticks2msecs(x, x->s_tempo_value(tempondx)); + tempondx++; + } + thistime = temposince + (thisonset - tempoonset) * coef; +#endif + if (thistime < lasttime) + { +#ifdef SQ_DEBUG + /* FIXME under msvc -- horror! */ + if (thistime != lasttime) + post("ndx %d, this-last (%x-%x) %.15f, \ +tix %.9f, tsince %.9f, ttix %.9f, coef %.9f", + tempondx, (int)thistime, (int)lasttime, + thistime - lasttime, + thisonset, temposince, tempoonset, coef); +#endif + thistime = lasttime; + } + /* back to delta time */ + if (ret) sethook(it, thistime - lasttime, &ret); + lasttime = thistime; + } + if (ret) incrhook(it); + else + { + post("sequence folding error: bad iterator"); + break; + } + } + } +} + +/* transform delta msecs into onset msecs */ +/* LATER add an option (or a separate function) for obtaining ticks + (according to tempomap) */ +void sq_unfold_time(t_sq *x) +{ + t_squiter *it = x->s_myiter; + t_squiter_seekhook seekhook = squiter_seekhook(it); + t_squiter_incrhook incrhook = squiter_incrhook(it); + t_squiter_gettimhook gethook = squiter_gettimhook(it); + t_squiter_settimhook sethook = squiter_settimhook(it); + int i, ret, nevents = x->s_nevents; + t_float thisonset = 0; + + if (!it || !seekhook(it, 0)) + return; + for (i = 0; i < nevents; i++) + { + if (ret = squiter_inrange(it)) + { + thisonset += gethook(it, &ret); + if (ret) sethook(it, thisonset, &ret); + } + if (ret) incrhook(it); + else + { + post("sequence unfolding error: bad iterator"); + break; + } + } +} + +void sq_reset(t_sq *x) +{ + x->s_eof = 0; + x->s_newtrack = 0; + x->s_anapass = 1; + x->s_fp = 0; + x->s_time = 0; + x->s_tempo = SQUMPI_DEFAULT; + x->s_track = 0; +} + +t_sq *sq_new(void) +{ + t_sq *x = (t_sq *)getbytes(sizeof(*x)); + if (!x) + goto constructorfailure; + + /* these two are allocated in derived structure constructor */ + x->s_myiter = 0; + x->s_auxeve = 0; + + if (!(x->s_mytempi = getbytes(sizeof(t_squmpi)))) + goto constructorfailure; + if (!(x->s_tempomap = getbytes(x->s_mytempi->m_bufsize = SQUMPI_NALLOC))) + goto constructorfailure; + x->s_ntempi = 0; + if (!(x->s_mytracks = getbytes(sizeof(t_squax)))) + goto constructorfailure; + if (!(x->s_trackmap = getbytes(x->s_mytracks->m_bufsize = SQUAX_NALLOC))) + goto constructorfailure; + x->s_ntracks = 0; + + x->s_autoalloc = 0; + x->s_format = 0; + x->s_nticks = 192; /* LATER parametrize this somehow */ + x->s_nframes = 0; + + sq_reset(x); + return (x); +constructorfailure: + if (x) sq_free(x); + return (0); +} + +void sq_free(t_sq *x) +{ + if (x->s_mytempi) + { + if (x->s_tempomap) + freebytes(x->s_tempomap, x->s_mytempi->m_bufsize); + freebytes(x->s_mytempi, sizeof(t_squmpi)); + } + if (x->s_mytracks) + { + if (x->s_trackmap) + freebytes(x->s_trackmap, x->s_mytracks->m_bufsize); + freebytes(x->s_mytracks, sizeof(t_squax)); + } + if (x->s_myiter) + freebytes(x->s_myiter, sizeof(*x->s_myiter)); + freebytes(x, sizeof(*x)); +} diff --git a/shared/common/sq.h b/shared/common/sq.h new file mode 100644 index 0000000..6b7586e --- /dev/null +++ b/shared/common/sq.h @@ -0,0 +1,169 @@ +/* Copyright (c) 2001-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* squeak and squeal: sequencing utilities, a prototype version + (the main, 'sq' part of the library) */ +/* LATER move everything not needed in mifi to squeal */ + +#ifndef __SQ_H__ +#define __SQ_H__ + +/* Generic buffer structure, the `base' for t_squeve, t_squmpi and t_squax */ +typedef struct _squb +{ + uint32 b_length; /* length of data currently used (in items) */ + uchar *b_data; /* data buffer */ + size_t b_bufsize; /* allocated size of data buffer (in bytes) */ +} t_squb; + +/* Generic event structure. Designed as an interface to squeak routines, + and not to be kept in arrays or lists (use sequence containers instead). + Data buffer is automatically allocated and resized by those routines. */ +typedef struct _squeve +{ + uint32 e_length; /* set for any event type! */ + uchar *e_data; + size_t e_bufsize; + uint32 e_delay; +} t_squeve; + +/* tempo map element */ +typedef struct _squmpo +{ + t_float te_onset; /* ticks or microseconds from start of sequence */ + uint32 te_value; /* microseconds per beat */ +} t_squmpo; + +typedef struct _squmpi +{ + uint32 m_ntempi; + t_squmpo *m_map; + size_t m_bufsize; /* allocated size of m_map array in bytes */ +} t_squmpi; + +/* track/subtrack map element */ +typedef struct _squack +{ + int tr_id; /* according to target template */ + uint32 tr_nevents; /* number of events (in this track or pre-total) */ + t_symbol *tr_name; /* track name */ + void *tr_head; /* pointer to first event */ +} t_squack; + +typedef struct _squax +{ + uint32 m_ntracks; + t_squack *m_map; + size_t m_bufsize; /* allocated size of m_map array in bytes */ +} t_squax; + +/* generic type of callback routines used to read/write + sequence containers through t_squiter */ +typedef int (*t_squiterhook)(void *it); + +#define SQUITER_SEEKHOOK 0 +#define SQUITER_INCRHOOK 1 +#define SQUITER_GETEVEHOOK 2 +#define SQUITER_SETEVEHOOK 3 +#define SQUITER_GETTIMHOOK 4 +#define SQUITER_SETTIMHOOK 5 +#define SQUITER_GETTARHOOK 6 +#define SQUITER_SETTARHOOK 7 +#define SQUITER_NHOOKS 8 +/* LATER move these typedefs to sq.c, if still not used globally */ +typedef int (*t_squiter_seekhook)(void *it, int offset); +typedef void (*t_squiter_incrhook)(void *it); +typedef void (*t_squiter_getevehook)(void *it, t_squeve *evp, int *ret); +typedef void (*t_squiter_setevehook)(void *it, t_squeve *evp, int *ret); +typedef t_float (*t_squiter_gettimhook)(void *it, int *ret); +typedef void (*t_squiter_settimhook)(void *it, t_float v, int *ret); +typedef t_symbol (*t_squiter_gettarhook)(void *it, int *ret); +typedef void (*t_squiter_settarhook)(void *it, t_symbol *s, int *ret); + +/* elements might be 'atoms' or whole events, whatever suits better */ +typedef struct _squiter +{ + void *i_owner; + int i_nelems; + void *i_sequence; /* first element pointer */ + void *i_element; /* current element pointer */ + int i_index; /* current element index */ + t_squiterhook i_hooks[SQUITER_NHOOKS]; +} t_squiter; + +/* This is a good candidate for a derivation hierarchy. */ +typedef struct _sq +{ + t_squiter *s_myiter; + t_squax *s_mytracks; + t_squmpi *s_mytempi; /* use shortcuts #defined below */ + void *s_auxeve; /* auxiliary event */ + uint32 s_nevents; /* total number of events */ + FILE *s_fp; /* hmm... */ + int s_autoalloc:1; /* set if auto-allocated */ + int s_eof:1; /* reading: set in case of early eof (error) */ + int s_newtrack:1; /* reading: set if first event in a track */ + int s_anapass:1; /* read/write: set during analysis (pass #1) */ + uchar s_nframes; /* fps if nonzero, else use metrical time */ + uint16 s_nticks; /* number of ticks per beat or per frame */ + uint16 s_format; /* `ismultitrack' flag, LATER add other formats */ + uint32 s_time; /* current time in ticks */ + uint32 s_tempo; /* current tempo, or last one encountered in a file */ + int s_trackid; /* LATER remove? */ + uint16 s_track; /* current track number */ + + /* fields below are specific to midifile streams */ + uchar s_status; /* current running status, | channel in writing */ + uchar s_channel; /* current channel, not used in writing */ + uint16 s_hdtracks; /* number of tracks declared in a midifile header */ + uint32 s_alltracks; /* total number of nonempty tracks */ + /* (s_ntracks counts `in range' nonempty tracks) */ + float s_timecoef; /* msecs->ticks, used in writing only */ + uint32 s_bytesleft; /* nbytes remaining to be read from current track, + or number of bytes written to a track so far */ +} t_sq; + +#define s_ntempi s_mytempi->m_ntempi +#define s_tempomap s_mytempi->m_map +#define s_tempo_onset(ndx) s_mytempi->m_map[ndx].te_onset +#define s_tempo_value(ndx) s_mytempi->m_map[ndx].te_value +#define s_ntracks s_mytracks->m_ntracks +#define s_trackmap s_mytracks->m_map +#define s_track_id(ndx) s_mytracks->m_map[ndx].tr_id +#define s_track_nevents(ndx) s_mytracks->m_map[ndx].tr_nevents +#define s_track_name(ndx) s_mytracks->m_map[ndx].tr_name +#define s_track_head(ndx) s_mytracks->m_map[ndx].tr_head + +/* prototypes of public interface routines */ + +size_t squb_checksize(void *buf, size_t reqcount, size_t elsize); + +#define squiter_inrange(it) ((it)->i_index < (it)->i_nelems) +void *squiter_new(t_sq *x); +t_squiter_seekhook squiter_seekhook(t_squiter *x); +t_squiter_incrhook squiter_incrhook(t_squiter *x); +t_squiter_getevehook squiter_getevehook(t_squiter *x); +t_squiter_setevehook squiter_setevehook(t_squiter *x); +t_squiter_gettimhook squiter_gettimhook(t_squiter *x); +t_squiter_settimhook squiter_settimhook(t_squiter *x); +t_squiter_gettarhook squiter_gettarhook(t_squiter *x); +t_squiter_settarhook squiter_settarhook(t_squiter *x); + +void squmpi_sort(t_sq *x); +t_squmpo *squmpi_add(t_sq *x); +void squmpo_reset(t_squmpo *x); +t_squack *squax_add(t_sq *x); +void squack_reset(t_squack *x); + +float sq_ticks2msecs(t_sq *x, uint32 tempo); +float sq_msecs2ticks(t_sq *x, uint32 tempo); + +void sq_fold_time(t_sq *x); +void sq_unfold_time(t_sq *x); + +t_sq *sq_new(void); +void sq_reset(t_sq *x); +void sq_free(t_sq *x); + +#endif diff --git a/shared/common/vefl.c b/shared/common/vefl.c new file mode 100644 index 0000000..19f37a2 --- /dev/null +++ b/shared/common/vefl.c @@ -0,0 +1,233 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The simplest of garrays: vector of floats */ + +/* Array checking is done in three points: + 1. vefl_new(): never complains + 2. vefl_renew(): this should be called once per every message + 3. vefl_tick(): no template checking (only redraw is involved) +*/ + +/* LATER rethink indsp flag */ + +#include "m_pd.h" +#include "g_canvas.h" +#include "shared.h" +#include "unstable/fragile.h" +#include "common/loud.h" +#include "common/vefl.h" + +#if 1 +#define VEFL_VERBOSE +#if 0 +#define VEFL_DEBUG +#endif +#endif + +/* on failure *vszp is not modified */ +t_float *vefl_get(t_symbol *name, int *vszp, int indsp, t_pd *complain) +{ + if (name && name != &s_) + { + t_garray *ap = (t_garray *)pd_findbyclass(name, garray_class); + if (ap) + { + int vsz; + t_float *vec; + if (garray_getfloatarray(ap, &vsz, &vec)) + { + if (indsp) garray_usedindsp(ap); + if (vszp) *vszp = vsz; + return (vec); + } + else loud_error(complain, /* always complain */ + "bad template of array '%s'", name->s_name); + } + else if (complain) + loud_error(complain, "no such array '%s'", name->s_name); + } + return (0); +} + +static void vefl_tick(t_vefl *vp) +{ + if (vp->v_name && vp->v_name != &s_ + /* Check if an array has not been deleted + (e.g. during patch closing sequence). */ + && (vp->v_garray = + (t_garray *)pd_findbyclass(vp->v_name, garray_class))) + { + vp->v_glist = fragile_garray_glist(vp->v_garray); + garray_redraw(vp->v_garray); + } + vp->v_clockset = 0; + vp->v_updtime = clock_getsystime(); +} + +t_vefl *vefl_placement_new(t_vefl *vp, t_symbol *name, + int writable, t_glist *gl, t_garray *arr) +{ + if (sizeof(t_word) != sizeof(t_float)) + { + bug("vefl_new: sizeof(t_word) != sizeof(t_float)"); + return (0); + } + if (!vp) + { + if (!(vp = getbytes(sizeof(*vp)))) + return (0); + vp->v_autoalloc = 1; + } + else vp->v_autoalloc = 0; + vp->v_name = name; + if (writable) + { + vp->v_updtime = clock_getsystime(); + vp->v_clock = clock_new(vp, (t_method)vefl_tick); + vp->v_clockset = 0; + } + else vp->v_clock = 0; + vp->v_glist = gl; + vp->v_garray = arr; + vp->v_size = 0; + vp->v_data = 0; + vp->v_type = &s_float; + if (!arr && name && name != &s_) + { + vp->v_garray = (t_garray *)pd_findbyclass(name, garray_class); + vp->v_glist = vp->v_garray ? fragile_garray_glist(vp->v_garray) : 0; + } + if (vp->v_garray + && !garray_getfloatarray(vp->v_garray, &vp->v_size, &vp->v_data)) + { + vp->v_glist = 0; + vp->v_garray = 0; + vp->v_type = 0; /* template mismatch */ + } + return (vp); +} + +t_vefl *vefl_new(t_symbol *name, int writable, t_glist *gl, t_garray *arr) +{ + return (vefl_placement_new(0, name, writable, gl, arr)); +} + +void vefl_free(t_vefl *vp) +{ + if (vp->v_clock) clock_free(vp->v_clock); + if (vp->v_autoalloc) freebytes(vp, sizeof(*vp)); +} + +/* LATER handle yonset */ +int vefl_renew(t_vefl *vp, t_symbol *name, t_pd *complain) +{ + if (!name || name == &s_) name = vp->v_name; + if (name && name != &s_) + { + vp->v_glist = 0; + /* There are three possible ways: */ +#if 0 + vp->v_name = 0; +#elif 1 /* , do nothing, and */ + vp->v_name = name; +#endif /* LATER check all the cases and decide... */ + if (!(vp->v_garray = (t_garray *)pd_findbyclass(name, garray_class))) + { + if (complain) + loud_error(complain, "no such array '%s'", name->s_name); + } + else if (!garray_getfloatarray(vp->v_garray, &vp->v_size, &vp->v_data)) + { + vp->v_garray = 0; + loud_error(complain, /* always complain */ + "bad template of array '%s'", name->s_name); + } + else + { + vp->v_glist = fragile_garray_glist(vp->v_garray); + vp->v_name = name; + return (1); + } + } + return (0); +} + +void vefl_redraw(t_vefl *vp, float suppresstime) +{ + if (vp->v_clock) /* requests from readers are ignored */ + { + if (suppresstime > 0) + { + double timesince = clock_gettimesince(vp->v_updtime); + if (timesince > suppresstime) + { + clock_unset(vp->v_clock); + vefl_tick(vp); + } + else if (!vp->v_clockset) + { + clock_delay(vp->v_clock, suppresstime - timesince); + vp->v_clockset = 1; + } + } + else { + clock_unset(vp->v_clock); + vefl_tick(vp); + } + } +} + +void vefl_redraw_stop(t_vefl *vp) +{ + if (vp->v_clock) /* requests from readers are ignored */ + { + clock_unset(vp->v_clock); + vp->v_clockset = 0; + } +} + +/* Y-bounds flipped here */ +void vefl_getbounds(t_vefl *vp, t_float *xminp, t_float *yminp, + t_float *xmaxp, t_float *ymaxp) +{ + t_glist *gl = vp->v_glist; + if (gl) + { + *xminp = gl->gl_x1; + *xmaxp = gl->gl_x2; + *yminp = gl->gl_y2; + *ymaxp = gl->gl_y1; + } +} + +/* Y-bounds flipped here */ +void vefl_setbounds(t_vefl *vp, t_float xmin, t_float ymin, + t_float xmax, t_float ymax) +{ + vmess((t_pd *)vp->v_glist, gensym("bounds"), "ffff", + xmin, ymax, xmax, ymin); +} + +void vefl_getrange(t_vefl *vp, t_float *yminp, t_float *ymaxp) +{ + int vsz = vp->v_size; + t_float *vec = vp->v_data; + if (vec && vsz) + { + t_float ymin = SHARED_FLT_MAX, ymax = -SHARED_FLT_MAX; + while (vsz--) + { + if (*vec > ymax) + { + ymax = *vec; + if (ymax < ymin) ymin = ymax; + } + else if (*vec < ymin) ymin = *vec; + vec++; + } + *yminp = ymin; + *ymaxp = ymax; + } +} diff --git a/shared/common/vefl.h b/shared/common/vefl.h new file mode 100644 index 0000000..e470a80 --- /dev/null +++ b/shared/common/vefl.h @@ -0,0 +1,36 @@ +/* Copyright (c) 2001-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __VEFL_H__ +#define __VEFL_H__ + +typedef struct _vefl +{ + int v_autoalloc; + t_symbol *v_name; + t_glist *v_glist; + t_garray *v_garray; + int v_size; + t_float *v_data; + t_symbol *v_type; + t_clock *v_clock; + int v_clockset; + double v_updtime; +} t_vefl; + +t_float *vefl_get(t_symbol *name, int *vszp, int indsp, t_pd *complain); +t_vefl *vefl_new(t_symbol *name, int writable, t_glist *gl, t_garray *arr); +t_vefl *vefl_placement_new(t_vefl *vp, t_symbol *name, + int writable, t_glist *gl, t_garray *arr); +void vefl_free(t_vefl *vp); +int vefl_renew(t_vefl *vp, t_symbol *name, t_pd *complain); +void vefl_redraw(t_vefl *vp, float suppresstime); +void vefl_redraw_stop(t_vefl *vp); +void vefl_getbounds(t_vefl *vp, t_float *xminp, t_float *yminp, + t_float *xmaxp, t_float *ymaxp); +void vefl_setbounds(t_vefl *vp, t_float xmin, t_float ymin, + t_float xmax, t_float ymax); +void vefl_getrange(t_vefl *vp, t_float *yminp, t_float *ymaxp); + +#endif diff --git a/shared/hammer/Makefile b/shared/hammer/Makefile new file mode 100644 index 0000000..5dcb2c8 --- /dev/null +++ b/shared/hammer/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR = ../.. +include $(ROOT_DIR)/Makefile.common + +all: $(OBJECTS) diff --git a/shared/hammer/Makefile.objects b/shared/hammer/Makefile.objects new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/shared/hammer/Makefile.objects diff --git a/shared/hammer/Makefile.sources b/shared/hammer/Makefile.sources new file mode 100644 index 0000000..5a6d99a --- /dev/null +++ b/shared/hammer/Makefile.sources @@ -0,0 +1,4 @@ +OTHER_SOURCES = \ +file.c \ +gui.c \ +tree.c diff --git a/shared/hammer/file.c b/shared/hammer/file.c new file mode 100644 index 0000000..6a94c92 --- /dev/null +++ b/shared/hammer/file.c @@ -0,0 +1,402 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* The three uses of the 'hammerfile' proxy class are: + 1. providing `embedding' facility -- storing master object's state + in a .pd file, + 2. encapsulating openpanel/savepanel management, + 3. extending the gui of Pd with a simple text editor window. + + A master class which needs embedding feature (like coll), passes + a nonzero flag to the hammerfile setup routine, and a nonzero embedfn + function pointer to the hammerfile constructor. If a master needs + access to the panels (like collcommon), then it passes nonzero readfn + and/or writefn callback pointers to the constructor. A master which has + an associated text editor, AND wants to update object's state after + edits, passes a nonzero updatefn callback in a call to the constructor. */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "g_canvas.h" +/* need this for t_class::c_wb field access, LATER find a better way... */ +#include "unstable/pd_imp.h" +#include "hammer/file.h" + +static t_class *hammerfile_class = 0; +static t_hammerfile *hammerfile_proxies; +static t_symbol *ps__C; + +static t_hammerfile *hammerfile_getproxy(t_pd *master) +{ + t_hammerfile *f; + for (f = hammerfile_proxies; f; f = f->f_next) + if (f->f_master == master) + return (f); + return (0); +} + +/* FIXME somehow plug the "save changes" dialog into close-by-wm */ +/* FIXME dirty condition */ +static void hammereditor_guidefs(void) +{ + sys_gui("proc hammereditor_open {name geometry title} {\n"); + sys_gui(" if {[winfo exists $name]} {\n"); + sys_gui(" $name.text delete 1.0 end\n"); + sys_gui(" } else {\n"); + sys_gui(" toplevel $name\n"); + sys_gui(" wm title $name $title\n"); + sys_gui(" wm geometry $name $geometry\n"); + sys_gui(" text $name.text -relief raised -bd 2 \\\n"); + sys_gui(" -font -*-courier-medium--normal--12-* \\\n"); + sys_gui(" -yscrollcommand \"$name.scroll set\" -background lightgrey\n"); + sys_gui(" scrollbar $name.scroll -command \"$name.text yview\"\n"); + sys_gui(" pack $name.scroll -side right -fill y\n"); + sys_gui(" pack $name.text -side left -fill both -expand 1\n"); + sys_gui(" }\n"); + sys_gui("}\n"); + + sys_gui("proc hammereditor_doclose {name} {\n"); + sys_gui(" destroy $name\n"); + sys_gui("}\n"); + + sys_gui("proc hammereditor_append {name contents} {\n"); + sys_gui(" if {[winfo exists $name]} {\n"); + sys_gui(" $name.text insert end $contents\n"); + sys_gui(" }\n"); + sys_gui("}\n"); + + /* FIXME make it more reliable */ + sys_gui("proc hammereditor_send {name} {\n"); + sys_gui(" if {[winfo exists $name]} {\n"); + sys_gui(" set ii [$name.text index [concat end - 1 lines]]\n"); + sys_gui(" pd [concat miXed$name clear \\;]\n"); + sys_gui(" for {set i 1} \\\n"); + sys_gui(" {[$name.text compare $i.end < $ii]} \\\n"); + sys_gui(" {incr i 1} {\n"); + sys_gui(" set lin [$name.text get $i.0 $i.end]\n"); + sys_gui(" if {$lin != \"\"} {\n"); + /* LATER rethink semi/comma mapping */ + sys_gui(" regsub -all \\; $lin \" _semi_ \" tmplin\n"); + sys_gui(" regsub -all \\, $tmplin \" _comma_ \" lin\n"); + sys_gui(" pd [concat miXed$name addline $lin \\;]\n"); + sys_gui(" }\n"); + sys_gui(" }\n"); + sys_gui(" pd [concat miXed$name end \\;]\n"); + sys_gui(" }\n"); + sys_gui("}\n"); + + sys_gui("proc hammereditor_close {name ask} {\n"); + sys_gui(" if {[winfo exists $name]} {\n"); + sys_gui(" set dirty $ask\n"); /* FIXME */ + sys_gui(" if {$dirty == 0} {hammereditor_doclose $name} else {\n"); + sys_gui(" set title [wm title $name]\n"); + sys_gui(" set answer [tk_messageBox \\-type yesnocancel \\\n"); + sys_gui(" \\-icon question \\\n"); + sys_gui(" \\-message [concat Save changes to $title?]]\n"); + sys_gui(" if {$answer == \"yes\"} {hammereditor_send $name}\n"); + sys_gui(" if {$answer != \"cancel\"} {hammereditor_doclose $name}\n"); + sys_gui(" }\n"); + sys_gui(" }\n"); + sys_gui("}\n"); +} + +void hammereditor_open(t_hammerfile *f, char *title) +{ + if (!title) title = class_getname(*f->f_master); + sys_vgui("hammereditor_open .%x %dx%d {%s}\n", (int)f, 600, 340, title); +} + +static void hammereditor_tick(t_hammerfile *f) +{ + sys_vgui("hammereditor_close .%x %d\n", (int)f, 1); +} + +void hammereditor_close(t_hammerfile *f, int ask) +{ + if (ask) + /* hack: deferring modal dialog creation in order to allow for + a message box redraw to happen -- LATER investigate */ + clock_delay(f->f_editorclock, 0); + else + sys_vgui("hammereditor_close .%x %d\n", (int)f, 0); +} + +void hammereditor_append(t_hammerfile *f, char *contents) +{ + if (!contents) contents = ""; + sys_vgui("hammereditor_append .%x {%s}\n", (int)f, contents); +} + +static void hammereditor_clear(t_hammerfile *f) +{ + if (f->f_editorfn) + { + if (f->f_binbuf) + binbuf_clear(f->f_binbuf); + else + f->f_binbuf = binbuf_new(); + } +} + +static void hammereditor_addline(t_hammerfile *f, + t_symbol *s, int ac, t_atom *av) +{ + if (f->f_editorfn) + { + int i; + t_atom *ap; + for (i = 0, ap = av; i < ac; i++, ap++) + { + if (ap->a_type == A_SYMBOL) + { + /* LATER rethink semi/comma mapping */ + if (!strcmp(ap->a_w.w_symbol->s_name, "_semi_")) + SETSEMI(ap); + else if (!strcmp(ap->a_w.w_symbol->s_name, "_comma_")) + SETCOMMA(ap); + } + } + binbuf_add(f->f_binbuf, ac, av); + } +} + +static void hammereditor_end(t_hammerfile *f) +{ + if (f->f_editorfn) + { + (*f->f_editorfn)(f->f_master, 0, binbuf_getnatom(f->f_binbuf), + binbuf_getvec(f->f_binbuf)); + binbuf_clear(f->f_binbuf); + } +} + +static void hammerpanel_guidefs(void) +{ + sys_gui("proc hammerpanel_save {target inidir inifile} {\n"); + sys_gui(" if {$inifile != \"\"} {\n"); + sys_gui(" set filename [tk_getSaveFile \\\n"); + sys_gui(" -initialdir $inidir -initialfile $inifile]\n"); + sys_gui(" } else {\n"); + sys_gui(" set filename [tk_getSaveFile]\n"); + sys_gui(" }\n"); + sys_gui(" if {$filename != \"\"} {\n"); + sys_gui(" pd [concat $target symbol [pdtk_enquote $filename] \\;]\n"); + sys_gui(" }\n"); + sys_gui("}\n"); +} + +static void hammerpanel_symbol(t_hammerfile *f, t_symbol *s) +{ + if (s && s != &s_ && f->f_panelfn) + (*f->f_panelfn)(f->f_master, s, 0, 0); +} + +static void hammerpanel_tick(t_hammerfile *f) +{ + if (f->f_savepanel) + sys_vgui("pdtk_openpanel %s\n", f->f_bindname->s_name); + else + sys_vgui("hammerpanel_save %s {%s} {%s}\n", f->f_bindname->s_name, + f->f_inidir->s_name, f->f_inifile->s_name); +} + +/* these are hacks: deferring modal dialog creation in order to allow for + a message box redraw to happen -- LATER investigate */ +void hammerpanel_open(t_hammerfile *f) +{ + clock_delay(f->f_panelclock, 0); +} + +void hammerpanel_save(t_hammerfile *f, t_symbol *inidir, t_symbol *inifile) +{ + /* LATER ask if we can rely on s_ pointing to "" */ + f->f_savepanel->f_inidir = (inidir ? inidir : &s_); + f->f_savepanel->f_inifile = (inifile ? inifile : &s_); + clock_delay(f->f_savepanel->f_panelclock, 0); +} + +/* Currently embeddable hammer classes do not use the 'saveto' method. + In order to use it, any embeddable class would have to add a creation + method to pd_canvasmaker -- then saving could be done with a 'proper' + sequence: #N <master> <args>; #X <whatever>; ...; #X restore <x> <y>; + However, this works only for -lib externals. So, we choose a sequence: + #X obj <x> <y> <master> <args>; #C <whatever>; ...; #C restore; + Since the first message in this sequence is a valid creation message + on its own, we have to distinguish loading from a .pd file, and other + cases (editing). */ + +static void hammerembed_gc(t_pd *x, t_symbol *s, int expected) +{ + t_pd *garbage; + int count = 0; + while (garbage = pd_findbyclass(s, *x)) pd_unbind(garbage, s), count++; + if (count != expected) + bug("hammerembed_gc (%d garbage bindings)", count); +} + +static void hammerembed_restore(t_pd *master) +{ + hammerembed_gc(master, ps__C, 1); +} + +void hammerembed_save(t_gobj *master, t_binbuf *bb) +{ + t_hammerfile *f = hammerfile_getproxy((t_pd *)master); + t_text *t = (t_text *)master; + binbuf_addv(bb, "ssii", &s__X, gensym("obj"), + (int)t->te_xpix, (int)t->te_ypix); + binbuf_addbinbuf(bb, t->te_binbuf); + binbuf_addsemi(bb); + if (f && f->f_embedfn) + (*f->f_embedfn)(f->f_master, bb, ps__C); + binbuf_addv(bb, "ss;", ps__C, gensym("restore")); +} + +int hammerfile_ismapped(t_hammerfile *f) +{ + return (f->f_canvas->gl_mapped); +} + +int hammerfile_isloading(t_hammerfile *f) +{ + return (f->f_canvas->gl_loading); +} + +/* LATER find a better way */ +int hammerfile_ispasting(t_hammerfile *f) +{ + int result = 0; + t_canvas *cv = f->f_canvas; + if (!cv->gl_loading) + { + t_pd *z = s__X.s_thing; + if (z == (t_pd *)cv) + { + pd_popsym(z); + if (s__X.s_thing == (t_pd *)cv) result = 1; + pd_pushsym(z); + } + else if (z) result = 1; + } +#if 0 + if (result) post("pasting"); +#endif + return (result); +} + +void hammerfile_free(t_hammerfile *f) +{ + t_hammerfile *prev, *next; + hammereditor_close(f, 0); + if (f->f_embedfn) + /* just in case of missing 'restore' */ + hammerembed_gc(f->f_master, ps__C, 0); + if (f->f_savepanel) + { + pd_unbind((t_pd *)f->f_savepanel, f->f_savepanel->f_bindname); + pd_free((t_pd *)f->f_savepanel); + } + if (f->f_bindname) pd_unbind((t_pd *)f, f->f_bindname); + if (f->f_panelclock) clock_free(f->f_panelclock); + if (f->f_editorclock) clock_free(f->f_editorclock); + for (prev = 0, next = hammerfile_proxies; + next; prev = next, next = next->f_next) + if (next == f) + break; + if (prev) + prev->f_next = f->f_next; + else if (f == hammerfile_proxies) + hammerfile_proxies = f->f_next; + pd_free((t_pd *)f); +} + +t_hammerfile *hammerfile_new(t_pd *master, t_hammerembedfn embedfn, + t_hammerfilefn readfn, t_hammerfilefn writefn, + t_hammerfilefn updatefn) +{ + t_hammerfile *result = (t_hammerfile *)pd_new(hammerfile_class); + result->f_master = master; + result->f_next = hammerfile_proxies; + hammerfile_proxies = result; + if (!(result->f_canvas = canvas_getcurrent())) + { + bug("hammerfile_new: out of context"); + return (result); + } + + /* 1. embedding */ + if (result->f_embedfn = embedfn) + { + /* just in case of missing 'restore' */ + hammerembed_gc(master, ps__C, 0); + if (hammerfile_isloading(result) || hammerfile_ispasting(result)) + pd_bind(master, ps__C); + } + + /* 2. the panels */ + if (readfn || writefn) + { + t_hammerfile *f; + char buf[64]; + sprintf(buf, "miXed.%x", (int)result); + result->f_bindname = gensym(buf); + pd_bind((t_pd *)result, result->f_bindname); + result->f_panelfn = readfn; + result->f_panelclock = clock_new(result, (t_method)hammerpanel_tick); + f = (t_hammerfile *)pd_new(hammerfile_class); + f->f_master = master; + sprintf(buf, "miXed.%x", (int)f); + f->f_bindname = gensym(buf); + pd_bind((t_pd *)f, f->f_bindname); + f->f_panelfn = writefn; + f->f_panelclock = clock_new(f, (t_method)hammerpanel_tick); + result->f_savepanel = f; + } + else result->f_savepanel = 0; + + /* 3. editor */ + if (result->f_editorfn = updatefn) + { + result->f_editorclock = clock_new(result, (t_method)hammereditor_tick); + if (!result->f_bindname) + { + char buf[64]; + sprintf(buf, "miXed.%x", (int)result); + result->f_bindname = gensym(buf); + pd_bind((t_pd *)result, result->f_bindname); + } + } + return (result); +} + +void hammerfile_setup(t_class *c, int embeddable) +{ + if (embeddable) + { + t_widgetbehavior *newwb = getbytes(sizeof(*newwb)); /* never freed */ + *newwb = *c->c_wb; + newwb->w_savefn = hammerembed_save; + class_setwidget(c, newwb); + class_addmethod(c, (t_method)hammerembed_restore, + gensym("restore"), 0); + } + if (!hammerfile_class) + { + ps__C = gensym("#C"); + hammerfile_class = class_new(gensym("_hammerfile"), 0, 0, + sizeof(t_hammerfile), + CLASS_PD | CLASS_NOINLET, 0); + class_addsymbol(hammerfile_class, hammerpanel_symbol); + class_addmethod(hammerfile_class, (t_method)hammereditor_clear, + gensym("clear"), 0); + class_addmethod(hammerfile_class, (t_method)hammereditor_addline, + gensym("addline"), A_GIMME, 0); + class_addmethod(hammerfile_class, (t_method)hammereditor_end, + gensym("end"), 0); + /* LATER find a way of ensuring that these are not defined yet... */ + hammereditor_guidefs(); + hammerpanel_guidefs(); + } +} diff --git a/shared/hammer/file.h b/shared/hammer/file.h new file mode 100644 index 0000000..d0f6526 --- /dev/null +++ b/shared/hammer/file.h @@ -0,0 +1,43 @@ +/* Copyright (c) 2002-2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __HAMMERFILE_H__ +#define __HAMMERFILE_H__ + +typedef void (*t_hammerfilefn)(t_pd *, t_symbol *, int, t_atom *); +typedef void (*t_hammerembedfn)(t_pd *, t_binbuf *, t_symbol *); + +typedef struct _hammerfile +{ + t_pd f_pd; + t_pd *f_master; + t_canvas *f_canvas; + t_symbol *f_bindname; + t_symbol *f_inidir; + t_symbol *f_inifile; + t_hammerfilefn f_panelfn; + t_hammerfilefn f_editorfn; + t_hammerembedfn f_embedfn; + t_binbuf *f_binbuf; + t_clock *f_panelclock; + t_clock *f_editorclock; + struct _hammerfile *f_savepanel; + struct _hammerfile *f_next; +} t_hammerfile; + +void hammereditor_open(t_hammerfile *f, char *title); +void hammereditor_close(t_hammerfile *f, int ask); +void hammereditor_append(t_hammerfile *f, char *contents); +void hammerpanel_open(t_hammerfile *f); +void hammerpanel_save(t_hammerfile *f, t_symbol *inidir, t_symbol *inifile); +int hammerfile_ismapped(t_hammerfile *f); +int hammerfile_isloading(t_hammerfile *f); +int hammerfile_ispasting(t_hammerfile *f); +void hammerfile_free(t_hammerfile *f); +t_hammerfile *hammerfile_new(t_pd *master, t_hammerembedfn embedfn, + t_hammerfilefn readfn, t_hammerfilefn writefn, + t_hammerfilefn updatefn); +void hammerfile_setup(t_class *c, int embeddable); + +#endif diff --git a/shared/hammer/gui.c b/shared/hammer/gui.c new file mode 100644 index 0000000..5e98ff8 --- /dev/null +++ b/shared/hammer/gui.c @@ -0,0 +1,438 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* FIXME use guiconnect */ + +#include <stdio.h> +#include "m_pd.h" +#include "g_canvas.h" +#include "hammer/gui.h" + +//#define HAMMERGUI_DEBUG + +static t_class *hammergui_class = 0; +static t_hammergui *sink = 0; +static t_symbol *ps__up; +static t_symbol *ps__focus; +static t_symbol *ps__vised; + +static void hammergui_anything(t_hammergui *snk, + t_symbol *s, int ac, t_atom *av) +{ + /* Dummy method, filtering out messages from gui to the masters. This is + needed in order to keep Pd's message system happy in a ``gray period'' + -- after last master is unbound, and before gui bindings are cleared. */ +#ifdef HAMMERGUI_DEBUG + startpost("%s", s->s_name); + postatom(ac, av); + endpost(); +#endif +} + +/* filtering out redundant "_up" messages */ +static void hammergui__up(t_hammergui *snk, t_floatarg f) +{ +#ifdef HAMMERGUI_DEBUG + post("_up %g", f); +#endif + if ((int)f) + { + if (!snk->g_up) + { + snk->g_up = 1; + if (snk->g_mouse->s_thing) + { + t_atom at; + SETFLOAT(&at, 1); + pd_typedmess(snk->g_mouse->s_thing, ps__up, 1, &at); + } + } + } + else + { + if (snk->g_up) + { + snk->g_up = 0; + if (snk->g_mouse->s_thing) + { + t_atom at; + SETFLOAT(&at, 0); + pd_typedmess(snk->g_mouse->s_thing, ps__up, 1, &at); + } + } + } +} + +static void hammergui__focus(t_hammergui *snk, t_symbol *s, t_floatarg f) +{ +#ifdef HAMMERGUI_DEBUG + if (s) post("_focus %s %g", s->s_name, f); +#endif + if (snk->g_focus->s_thing) + { + t_atom at[2]; + SETSYMBOL(&at[0], s); + SETFLOAT(&at[1], f); + pd_typedmess(snk->g_focus->s_thing, ps__focus, 2, at); + } +} + +static void hammergui__vised(t_hammergui *snk, t_symbol *s, t_floatarg f) +{ +#ifdef HAMMERGUI_DEBUG + if (s) post("_vised %s %g", s->s_name, f); +#endif + if (snk->g_vised->s_thing) + { + t_atom at[2]; + SETSYMBOL(&at[0], s); + SETFLOAT(&at[1], f); + pd_typedmess(snk->g_vised->s_thing, ps__vised, 2, at); + } +#if 0 + /* How to be notified about changes of button state, prior to gui objects + in a canvas? LATER find a reliable way -- delete if failed */ + sys_vgui("bindtags %s {hammertag %s Canvas . all}\n", + s->s_name, s->s_name); +#endif +} + + +static void hammergui_dobindmouse(t_hammergui *snk) +{ +#if 0 + /* How to be notified about changes of button state, prior to gui objects + in a canvas? LATER find a reliable way -- delete if failed */ + sys_vgui("bind hammertag <<hammerdown>> {pd [concat %s _up 0 \\;]}\n", + snk->g_gui->s_name); + sys_vgui("bind hammertag <<hammerup>> {pd [concat %s _up 1 \\;]}\n", + snk->g_gui->s_name); +#endif + sys_vgui("bind all <<hammerdown>> {pd [concat %s _up 0 \\;]}\n", + snk->g_gui->s_name); + sys_vgui("bind all <<hammerup>> {pd [concat %s _up 1 \\;]}\n", + snk->g_gui->s_name); +} + +static void hammergui__remouse(t_hammergui *snk) +{ + if (snk->g_mouse->s_thing) + { + /* if a new master was bound in a gray period, we need to + restore gui bindings */ +#if 1 + post("rebinding mouse..."); +#endif + hammergui_dobindmouse(snk); + } +} + +static void hammergui_dobindfocus(t_hammergui *snk) +{ + sys_vgui("bind Canvas <<hammerfocusin>> \ + {pd [concat %s _focus %%W 1 \\;]}\n", snk->g_gui->s_name); + sys_vgui("bind Canvas <<hammerfocusout>> \ + {pd [concat %s _focus %%W 0 \\;]}\n", snk->g_gui->s_name); +} + +static void hammergui__refocus(t_hammergui *snk) +{ + if (snk->g_focus->s_thing) + { + /* if a new master was bound in a gray period, we need to + restore gui bindings */ +#if 1 + post("rebinding focus..."); +#endif + hammergui_dobindfocus(snk); + } +} + +static void hammergui_dobindvised(t_hammergui *snk) +{ + sys_vgui("bind Canvas <<hammervised>> \ + {pd [concat %s _vised %%W 1 \\;]}\n", snk->g_gui->s_name); + sys_vgui("bind Canvas <<hammerunvised>> \ + {pd [concat %s _vised %%W 0 \\;]}\n", snk->g_gui->s_name); +} + +static void hammergui__revised(t_hammergui *snk) +{ + if (snk->g_vised->s_thing) + { + /* if a new master was bound in a gray period, we need to + restore gui bindings */ +#if 1 + post("rebinding vised events..."); +#endif + hammergui_dobindvised(snk); + } +} + +static void hammergui_setup(void) +{ + hammergui_class = class_new(gensym("_hammergui"), 0, 0, + sizeof(t_hammergui), + CLASS_PD | CLASS_NOINLET, 0); + class_addanything(hammergui_class, hammergui_anything); + class_addmethod(hammergui_class, (t_method)hammergui__remouse, + gensym("_remouse"), 0); + class_addmethod(hammergui_class, (t_method)hammergui__refocus, + gensym("_refocus"), 0); + class_addmethod(hammergui_class, (t_method)hammergui__revised, + gensym("_revised"), 0); + ps__up = gensym("_up"); + class_addmethod(hammergui_class, (t_method)hammergui__up, + ps__up, A_FLOAT, 0); + ps__focus = gensym("_focus"); + class_addmethod(hammergui_class, (t_method)hammergui__focus, + ps__focus, A_SYMBOL, A_FLOAT, 0); + ps__vised = gensym("_vised"); + class_addmethod(hammergui_class, (t_method)hammergui__vised, + ps__vised, A_SYMBOL, A_FLOAT, 0); + + sys_gui("proc hammergui_remouse {} {\n"); + sys_gui(" bind all <<hammerdown>> {}\n"); + sys_gui(" bind all <<hammerup>> {}\n"); + sys_gui(" pd [concat #hammergui _remouse \\;]\n"); + sys_gui("}\n"); + + sys_gui("proc hammergui_mousexy {target} {\n"); + sys_gui(" set x [winfo pointerx .]\n"); + sys_gui(" set y [winfo pointery .]\n"); + sys_gui(" pd [concat #hammermouse $target $x $y \\;]\n"); + sys_gui("}\n"); + + /* visibility hack for msw, LATER rethink */ + sys_gui("global hammergui_ispolling\n"); + sys_gui("global hammergui_x\n"); + sys_gui("global hammergui_y\n"); + sys_gui("set hammergui_ispolling 0\n"); + sys_gui("set hammergui_x 0\n"); + sys_gui("set hammergui_y 0\n"); + + sys_gui("proc hammergui_poll {} {\n"); + sys_gui(" global hammergui_ispolling\n"); + sys_gui(" global hammergui_x\n"); + sys_gui(" global hammergui_y\n"); + sys_gui(" if {$hammergui_ispolling == 1} {\n"); + sys_gui(" set x [winfo pointerx .]\n"); + sys_gui(" set y [winfo pointery .]\n"); + sys_gui(" if {$hammergui_x != $x || $hammergui_y != $y} {\n"); + sys_gui(" pd [concat #hammermouse _poll $x $y \\;]\n"); + sys_gui(" set hammergui_x $x\n"); + sys_gui(" set hammergui_y $y\n"); + sys_gui(" }\n"); + sys_gui(" after 50 hammergui_poll\n"); + sys_gui(" }\n"); + sys_gui("}\n"); + + sys_gui("proc hammergui_refocus {} {\n"); + sys_gui(" bind Canvas <<hammerfocusin>> {}\n"); + sys_gui(" bind Canvas <<hammerfocusout>> {}\n"); + sys_gui(" pd [concat #hammergui _refocus \\;]\n"); + sys_gui("}\n"); + + sys_gui("proc hammergui_revised {} {\n"); + sys_gui(" bind Canvas <<hammervised>> {}\n"); + sys_gui(" bind Canvas <<hammerunvised>> {}\n"); + sys_gui(" pd [concat #hammergui _revised \\;]\n"); + sys_gui("}\n"); +} + +static int hammergui_validate(int dosetup) +{ + if (dosetup) + { + if (!hammergui_class) hammergui_setup(); + if (!sink) + { + sink = (t_hammergui *)pd_new(hammergui_class); + sink->g_gui = gensym("#hammergui"); + pd_bind((t_pd *)sink, sink->g_gui); + } + } + if (hammergui_class && sink) + return (1); + else + { + bug("hammergui_validate"); + return (0); + } +} + +static int hammergui_mousevalidate(int dosetup) +{ + if (dosetup && !sink->g_mouse) + { + sink->g_mouse = gensym("#hammermouse"); + sys_gui("event add <<hammerdown>> <ButtonPress>\n"); + sys_gui("event add <<hammerup>> <ButtonRelease>\n"); + } + if (sink->g_mouse) + return (1); + else + { + bug("hammergui_mousevalidate"); + return (0); + } +} + +static int hammergui_pollvalidate(int dosetup) +{ + if (dosetup && !sink->g_poll) + { + sink->g_poll = gensym("#hammerpoll"); + pd_bind((t_pd *)sink, sink->g_poll); /* never unbound */ + } + if (sink->g_poll) + return (1); + else + { + bug("hammergui_pollvalidate"); + return (0); + } +} + +static int hammergui_focusvalidate(int dosetup) +{ + if (dosetup && !sink->g_focus) + { + sink->g_focus = gensym("#hammerfocus"); + sys_gui("event add <<hammerfocusin>> <FocusIn>\n"); + sys_gui("event add <<hammerfocusout>> <FocusOut>\n"); + } + if (sink->g_focus) + return (1); + else + { + bug("hammergui_focusvalidate"); + return (0); + } +} + +static int hammergui_visedvalidate(int dosetup) +{ + if (dosetup && !sink->g_vised) + { + sink->g_vised = gensym("#hammervised"); + /* subsequent map events have to be filtered out at the caller's side, + LATER investigate */ + sys_gui("event add <<hammervised>> <Map>\n"); + sys_gui("event add <<hammerunvised>> <Destroy>\n"); + } + if (sink->g_vised) + return (1); + else + { + bug("hammergui_visedvalidate"); + return (0); + } +} + +void hammergui_bindmouse(t_pd *master) +{ + hammergui_validate(1); + hammergui_mousevalidate(1); + if (!sink->g_mouse->s_thing) + hammergui_dobindmouse(sink); + pd_bind(master, sink->g_mouse); +} + +void hammergui_unbindmouse(t_pd *master) +{ + if (hammergui_validate(0) && hammergui_mousevalidate(0) + && sink->g_mouse->s_thing) + { + pd_unbind(master, sink->g_mouse); + if (!sink->g_mouse->s_thing) + sys_gui("hammergui_remouse\n"); + } + else bug("hammergui_unbindmouse"); +} + +void hammergui_mousexy(t_symbol *s) +{ + if (hammergui_validate(0)) + sys_vgui("hammergui_mousexy %s\n", s->s_name); +} + +void hammergui_willpoll(void) +{ + hammergui_validate(1); + hammergui_pollvalidate(1); +} + +void hammergui_startpolling(t_pd *master) +{ + if (hammergui_validate(0) && hammergui_pollvalidate(0)) + { + int doinit = (sink->g_poll->s_thing == (t_pd *)sink); + pd_bind(master, sink->g_poll); + if (doinit) + { + /* visibility hack for msw, LATER rethink */ + sys_gui("global hammergui_ispolling\n"); + sys_gui("set hammergui_ispolling 1\n"); + sys_gui("hammergui_poll\n"); + } + } +} + +void hammergui_stoppolling(t_pd *master) +{ + if (hammergui_validate(0) && hammergui_pollvalidate(0)) + { + pd_unbind(master, sink->g_poll); + if (sink->g_poll->s_thing == (t_pd *)sink) + { + sys_gui("after cancel hammergui_poll\n"); + /* visibility hack for msw, LATER rethink */ + sys_gui("global hammergui_ispolling\n"); + sys_gui("set hammergui_ispolling 0\n"); + } + } +} + +void hammergui_bindfocus(t_pd *master) +{ + hammergui_validate(1); + hammergui_focusvalidate(1); + if (!sink->g_focus->s_thing) + hammergui_dobindfocus(sink); + pd_bind(master, sink->g_focus); +} + +void hammergui_unbindfocus(t_pd *master) +{ + if (hammergui_validate(0) && hammergui_focusvalidate(0) + && sink->g_focus->s_thing) + { + pd_unbind(master, sink->g_focus); + if (!sink->g_focus->s_thing) + sys_gui("hammergui_refocus\n"); + } + else bug("hammergui_unbindfocus"); +} + +void hammergui_bindvised(t_pd *master) +{ + hammergui_validate(1); + hammergui_visedvalidate(1); + if (!sink->g_vised->s_thing) + hammergui_dobindvised(sink); + pd_bind(master, sink->g_vised); +} + +void hammergui_unbindvised(t_pd *master) +{ + if (hammergui_validate(0) && hammergui_visedvalidate(0) + && sink->g_vised->s_thing) + { + pd_unbind(master, sink->g_vised); + if (!sink->g_vised->s_thing) + sys_gui("hammergui_revised\n"); + } + else bug("hammergui_unbindvised"); +} diff --git a/shared/hammer/gui.h b/shared/hammer/gui.h new file mode 100644 index 0000000..13afd0a --- /dev/null +++ b/shared/hammer/gui.h @@ -0,0 +1,30 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __HAMMERGUI_H__ +#define __HAMMERGUI_H__ + +typedef struct _hammergui +{ + t_pd g_pd; + t_symbol *g_gui; + t_symbol *g_mouse; + t_symbol *g_poll; + t_symbol *g_focus; + t_symbol *g_vised; + int g_up; +} t_hammergui; + +void hammergui_bindmouse(t_pd *master); +void hammergui_unbindmouse(t_pd *master); +void hammergui_mousexy(t_symbol *s); +void hammergui_willpoll(void); +void hammergui_startpolling(t_pd *master); +void hammergui_stoppolling(t_pd *master); +void hammergui_bindfocus(t_pd *master); +void hammergui_unbindfocus(t_pd *master); +void hammergui_bindvised(t_pd *master); +void hammergui_unbindvised(t_pd *master); + +#endif diff --git a/shared/hammer/tree.c b/shared/hammer/tree.c new file mode 100644 index 0000000..549dd09 --- /dev/null +++ b/shared/hammer/tree.c @@ -0,0 +1,482 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "hammer/tree.h" + +/* Since there is no sentinel node, the deletion routine has to have + a few extra checks. LATER rethink. */ + +/* LATER freelist */ + +#ifdef HAMMERTREE_DEBUG +/* returns bh or 0 if failed */ +static int hammernode_verify(t_hammernode *np) +{ + if (np) + { + int bhl, bhr; + if (((bhl = hammernode_verify(np->n_left)) == 0) || + ((bhr = hammernode_verify(np->n_right)) == 0)) + return (0); + if (bhl != bhr) + { + /* failure: two paths rooted in the same node + contain different number of black nodes */ + bug("hammernode_verify: not balanced"); + return (0); + } + if (np->n_black) + return (bhl + 1); + else + { + if ((np->n_left && !np->n_left->n_black) || + (np->n_right && !np->n_right->n_black)) + { + bug("hammernode_verify: adjacent red nodes"); + return (0); + } + return (bhl); + } + } + else return (1); +} + +/* returns bh or 0 if failed */ +static int hammertree_verify(t_hammertree *tree) +{ + return (hammernode_verify(tree->t_root)); +} + +static void hammernode_post(t_hammernode *np) +{ + startpost("%d %g %d (", np->n_index, np->n_value, np->n_black); + if (np->n_left) + startpost("%d, ", np->n_left->n_index); + else + startpost("nul, "); + if (np->n_right) + post("%d)", np->n_right->n_index); + else + post("nul)"); +} + +/* this is a standard stackless traversal, not the best one, obviously... + (used only for debugging) */ +static int hammertree_traverse(t_hammertree *tree, int postit) +{ + t_hammernode *np = tree->t_root; + int count = 0; + while (np) + { + t_hammernode *prev = np->n_left; + if (prev) + { + while (prev->n_right && prev->n_right != np) prev = prev->n_right; + if (prev->n_right) + { + prev->n_right = 0; + if (postit) hammernode_post(np); + count++; + np = np->n_right; + } + else + { + prev->n_right = np; + np = np->n_left; + } + } + else + { + if (postit) hammernode_post(np); + count++; + np = np->n_right; + } + } + return (count); +} + +static int hammernode_height(t_hammernode *np) +{ + if (np) + { + int lh = hammernode_height(np->n_left); + int rh = hammernode_height(np->n_right); + return (lh > rh ? lh + 1 : rh + 1); + } + else return (0); +} + +void hammertree_debug(t_hammertree *tree, int level) +{ + t_hammernode *np; + int count; + post("------------------------"); + count = hammertree_traverse(tree, level); + if (level > 1) + { + post("***"); + for (np = tree->t_last; np; np = np->n_prev) + startpost("%d ", np->n_index); + endpost(); + } + post("count %d, height %d, root %d:", + count, hammernode_height(tree->t_root), + (tree->t_root ? tree->t_root->n_index : 0)); + post("...verified (black-height is %d)", hammertree_verify(tree)); + post("------------------------"); +} +#endif + +/* assuming that target node (np->n_right) exists */ +static void hammertree_lrotate(t_hammertree *tree, t_hammernode *np) +{ + t_hammernode *target = np->n_right; + if (np->n_right = target->n_left) + np->n_right->n_parent = np; + if (!(target->n_parent = np->n_parent)) + tree->t_root = target; + else if (np == np->n_parent->n_left) + np->n_parent->n_left = target; + else + np->n_parent->n_right = target; + target->n_left = np; + np->n_parent = target; +} + +/* assuming that target node (np->n_left) exists */ +static void hammertree_rrotate(t_hammertree *tree, t_hammernode *np) +{ + t_hammernode *target = np->n_left; + if (np->n_left = target->n_right) + np->n_left->n_parent = np; + if (!(target->n_parent = np->n_parent)) + tree->t_root = target; + else if (np == np->n_parent->n_left) + np->n_parent->n_left = target; + else + np->n_parent->n_right = target; + target->n_right = np; + np->n_parent = target; +} + +/* returns a newly inserted or already existing node + (or 0 if allocation failed) */ +t_hammernode *hammertree_insert(t_hammertree *tree, int ndx) +{ + t_hammernode *np, *parent, *result; + if (!(np = tree->t_root)) + { + if (!(np = getbytes(sizeof(*np)))) + return (0); + np->n_index = ndx; + np->n_black = 1; + tree->t_root = tree->t_first = tree->t_last = np; + return (np); + } + + do + if (np->n_index == ndx) + return (np); + else + parent = np; + while (np = (ndx < np->n_index ? np->n_left : np->n_right)); + + if (!(np = getbytes(sizeof(*np)))) + return (0); + np->n_index = ndx; + np->n_parent = parent; + if (ndx < parent->n_index) + { + parent->n_left = np; + /* update the auxiliary linked list structure */ + np->n_next = parent; + if (np->n_prev = parent->n_prev) + np->n_prev->n_next = np; + else + tree->t_first = np; + parent->n_prev = np; + } + else + { + parent->n_right = np; + /* update the auxiliary linked list structure */ + np->n_prev = parent; + if (np->n_next = parent->n_next) + np->n_next->n_prev = np; + else + tree->t_last = np; + parent->n_next = np; + } + result = np; + + /* balance the tree -- LATER clean this if possible... */ + np->n_black = 0; + while (np != tree->t_root && !np->n_parent->n_black) + { + t_hammernode *uncle; + /* np->n_parent->n_parent exists (we always paint root node in black) */ + if (np->n_parent == np->n_parent->n_parent->n_left) + { + uncle = np->n_parent->n_parent->n_right; + if (!uncle /* (sentinel not used) */ + || uncle->n_black) + { + if (np == np->n_parent->n_right) + { + np = np->n_parent; + hammertree_lrotate(tree, np); + } + np->n_parent->n_black = 1; + np->n_parent->n_parent->n_black = 0; + hammertree_rrotate(tree, np->n_parent->n_parent); + } + else + { + np->n_parent->n_black = 1; + uncle->n_black = 1; + np = np->n_parent->n_parent; + np->n_black = 0; + } + } + else + { + uncle = np->n_parent->n_parent->n_left; + if (!uncle /* (sentinel not used) */ + || uncle->n_black) + { + if (np == np->n_parent->n_left) + { + np = np->n_parent; + hammertree_rrotate(tree, np); + } + np->n_parent->n_black = 1; + np->n_parent->n_parent->n_black = 0; + hammertree_lrotate(tree, np->n_parent->n_parent); + } + else + { + np->n_parent->n_black = 1; + uncle->n_black = 1; + np = np->n_parent->n_parent; + np->n_black = 0; + } + } + } + tree->t_root->n_black = 1; + return (result); +} + +/* assuming that requested node exists */ +void hammertree_delete(t_hammertree *tree, t_hammernode *np) +{ + t_hammernode *gone, *parent, *child; + /* gone is the actual node to be deleted + -- it has to be the parent of no more than one child: */ + if (np->n_left && np->n_right) + { + gone = np->n_next; /* gone always exists */ + child = gone->n_right; /* there is no left child of gone */ + /* gone is not a requested node, so we replace fields to be + deleted with gone's fields: */ + np->n_index = gone->n_index; + np->n_value = gone->n_value; + /* update the auxiliary linked list structure */ + /* np->n_prev is up-to-date */ + if (np->n_prev) + np->n_prev->n_next = np; + else tree->t_first = np; + if (np->n_next = gone->n_next) + np->n_next->n_prev = np; + else tree->t_last = np; + } + else + { + gone = np; + if (gone->n_left) + child = gone->n_left; + else + child = gone->n_right; + /* update the auxiliary linked list structure */ + if (gone->n_prev) + gone->n_prev->n_next = gone->n_next; + else + tree->t_first = gone->n_next; + if (gone->n_next) + gone->n_next->n_prev = gone->n_prev; + else + tree->t_last = gone->n_prev; + } + /* connect gone's child with gone's parent */ + if (!(parent = gone->n_parent)) + { + if (tree->t_root = child) + { + child->n_parent = 0; + child->n_black = 1; /* LATER rethink */ + } + goto done; + } + else + { + if (child) /* (sentinel not used) */ + child->n_parent = parent; + if (gone == parent->n_left) + parent->n_left = child; + else + parent->n_right = child; + } + + if (gone->n_black) + { + /* balance the tree -- LATER clean this if possible... */ + /* on entry: tree is not empty, parent always exists, child + not necessarily... */ + while (child != tree->t_root && + (!child || /* (sentinel not used) */ + child->n_black)) + { + t_hammernode *other; /* another child of the same parent */ + if (child == parent->n_left) + { + other = parent->n_right; + if (other && /* (sentinel not used) */ + !other->n_black) + { + other->n_black = 1; + parent->n_black = 0; + hammertree_lrotate(tree, parent); + other = parent->n_right; + } + if (!other || /* (sentinel not used) */ + (!other->n_left || other->n_left->n_black) && + (!other->n_right || other->n_right->n_black)) + { + if (other) /* (sentinel not used) */ + other->n_black = 0; + child = parent; + parent = parent->n_parent; + } + else + { + if (!other || /* (sentinel not used) */ + !other->n_right || other->n_right->n_black) + { + if (other) /* (sentinel not used) */ + { + if (other->n_left) other->n_left->n_black = 1; + other->n_black = 0; + hammertree_rrotate(tree, other); + other = parent->n_right; + } + } + if (other) /* (sentinel not used) */ + { + if (other->n_right) other->n_right->n_black = 1; + other->n_black = parent->n_black; + } + parent->n_black = 1; + hammertree_lrotate(tree, parent); + tree->t_root->n_black = 1; /* LATER rethink */ + goto done; + } + } + else /* right child */ + { + other = parent->n_left; + if (other && /* (sentinel not used) */ + !other->n_black) + { + other->n_black = 1; + parent->n_black = 0; + hammertree_rrotate(tree, parent); + other = parent->n_left; + } + if (!other || /* (sentinel not used) */ + (!other->n_left || other->n_left->n_black) && + (!other->n_right || other->n_right->n_black)) + { + if (other) /* (sentinel not used) */ + other->n_black = 0; + child = parent; + parent = parent->n_parent; + } + else + { + if (!other || /* (sentinel not used) */ + !other->n_left || other->n_left->n_black) + { + if (other) /* (sentinel not used) */ + { + if (other->n_right) other->n_right->n_black = 1; + other->n_black = 0; + hammertree_lrotate(tree, other); + other = parent->n_left; + } + } + if (other) /* (sentinel not used) */ + { + if (other->n_left) other->n_left->n_black = 1; + other->n_black = parent->n_black; + } + parent->n_black = 1; + hammertree_rrotate(tree, parent); + tree->t_root->n_black = 1; /* LATER rethink */ + goto done; + } + } + } + if (child) /* (sentinel not used) */ + child->n_black = 1; + } +done: + freebytes(gone, sizeof(*gone)); +#ifdef HAMMERTREE_DEBUG + hammertree_verify(tree); +#endif +} + +t_hammernode *hammertree_search(t_hammertree *tree, int ndx) +{ + t_hammernode *np = tree->t_root; + while (np && np->n_index != ndx) + np = (ndx < np->n_index ? np->n_left : np->n_right); + return (np); +} + +t_hammernode *hammertree_closest(t_hammertree *tree, int ndx, int geqflag) +{ + t_hammernode *np, *parent; + if (!(np = tree->t_root)) + return (0); + do + if (np->n_index == ndx) + return (np); + else + parent = np; + while (np = (ndx < np->n_index ? np->n_left : np->n_right)); + if (geqflag) + return (ndx > parent->n_index ? parent->n_next : parent); + else + return (ndx < parent->n_index ? parent->n_prev : parent); +} + +/* LATER preallocate 'freecount' nodes */ +void hammertree_init(t_hammertree *tree, int freecount) +{ + tree->t_root = tree->t_first = tree->t_last = 0; +} + +/* LATER keep and/or preallocate 'freecount' nodes (if negative, keep all) */ +void hammertree_clear(t_hammertree *tree, int freecount) +{ + t_hammernode *np, *next = tree->t_first; + while (next) + { + np = next; + next = next->n_next; + freebytes(np, sizeof(*np)); + } + hammertree_init(tree, 0); +} diff --git a/shared/hammer/tree.h b/shared/hammer/tree.h new file mode 100644 index 0000000..fcbc036 --- /dev/null +++ b/shared/hammer/tree.h @@ -0,0 +1,37 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __HAMMERTREE_H__ +#define __HAMMERTREE_H__ + +#define HAMMERTREE_DEBUG + +typedef struct _hammernode +{ + int n_index; + float n_value; + int n_black; + struct _hammernode *n_left; + struct _hammernode *n_right; + struct _hammernode *n_parent; + struct _hammernode *n_prev; + struct _hammernode *n_next; +} t_hammernode; + +typedef struct _hammertree +{ + t_hammernode *t_root; + t_hammernode *t_first; + t_hammernode *t_last; +} t_hammertree; + +t_hammernode *hammertree_insert(t_hammertree *tree, int ndx); +void hammertree_delete(t_hammertree *tree, t_hammernode *np); +t_hammernode *hammertree_search(t_hammertree *tree, int ndx); +t_hammernode *hammertree_closest(t_hammertree *tree, int ndx, int geqflag); +void hammertree_init(t_hammertree *tree, int freecount); +void hammertree_clear(t_hammertree *tree, int freecount); +void hammertree_debug(t_hammertree *tree, int level); + +#endif diff --git a/shared/shared.c b/shared/shared.c new file mode 100644 index 0000000..d6d2c98 --- /dev/null +++ b/shared/shared.c @@ -0,0 +1,11 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "shared.h" + +void shared_debug(void) +{ + /* LATER */ +} diff --git a/shared/shared.h b/shared/shared.h new file mode 100644 index 0000000..a0bd0e6 --- /dev/null +++ b/shared/shared.h @@ -0,0 +1,166 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __SHARED_H__ +#define __SHARED_H__ + +/* LATER find a proper place for #include <limits.h> */ +#ifdef INT_MAX +#define SHARED_INT_MAX INT_MAX +#else +#define SHARED_INT_MAX 0x7FFFFFFF +#endif +#ifdef INT_MIN +#define SHARED_INT_MIN INT_MIN +#else +#define SHARED_INT_MIN ((int)0x80000000) +#endif +/* LATER find a proper place for #include <float.h> */ +#ifdef FLT_MAX +#define SHARED_FLT_MAX FLT_MAX +#else +#define SHARED_FLT_MAX 1E+36 +#endif + +typedef unsigned long shared_t_bitmask; + +#ifdef __linux__ +#include <sys/types.h> +#ifndef int32 +typedef int32_t int32; +#endif +#ifndef uint32 +typedef u_int32_t uint32; +#endif +#ifndef int16 +typedef int16_t int16; +#endif +#ifndef uint16 +typedef u_int16_t uint16; +#endif +#ifndef uchar +typedef u_int8_t uchar; +#endif +#include <endian.h> +#if !defined(__BYTE_ORDER) || !defined(__LITTLE_ENDIAN) +#error No byte order defined +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SHARED_HIOFFSET 1 +#define SHARED_LOWOFFSET 0 +#else +#define SHARED_HIOFFSET 0 +#define SHARED_LOWOFFSET 1 +#endif +#endif + +#ifdef NT +#ifndef int32 +typedef long int32; +#endif +#ifndef uint32 +typedef unsigned long uint32; +#endif +#ifndef int16 +typedef short int16; +#endif +#ifndef uint16 +typedef unsigned short uint16; +#endif +#ifndef uchar +typedef unsigned char uchar; +#endif +#define SHARED_HIOFFSET 1 +#define SHARED_LOWOFFSET 0 +#endif + +#ifdef MACOSX +#ifndef int32 +typedef int int32; +#endif +#ifndef uint32 +typedef unsigned int uint32; +#endif +#ifndef int16 +typedef short int16; +#endif +#ifndef uint16 +typedef unsigned short uint16; +#endif +#ifndef uchar +typedef unsigned char uchar; +#endif +#define SHARED_HIOFFSET 0 +#define SHARED_LOWOFFSET 1 +#endif + +#ifdef IRIX +#ifndef int32 +typedef long int32; +#endif +#ifndef uint32 +typedef unsigned long uint32; +#endif +#ifndef int16 +typedef short int16; +#endif +#ifndef uint16 +typedef unsigned short uint16; +#endif +#ifndef uchar +typedef unsigned char uchar; +#endif +#define SHARED_HIOFFSET 0 +#define SHARED_LOWOFFSET 1 +#endif + +#ifdef __FreeBSD__ +#include <sys/types.h> +#ifndef int32 +typedef int32_t int32; +#endif +#ifndef uint32 +typedef u_int32_t uint32; +#endif +#ifndef int16 +typedef int16_t int16; +#endif +#ifndef uint16 +typedef u_int16_t uint16; +#endif +#ifndef uchar +typedef u_int8_t uchar; +#endif +#include <machine/endian.h> +#if BYTE_ORDER == LITTLE_ENDIAN +#define SHARED_HIOFFSET 1 +#define SHARED_LOWOFFSET 0 +#else +#define SHARED_HIOFFSET 0 +#define SHARED_LOWOFFSET 1 +#endif +#endif + +#define SHARED_UNITBIT32 1572864. /* 3*(2^19) gives 32 fractional bits */ +#define SHARED_UNITBIT0 6755399441055744. /* 3*(2^51), no fractional bits */ +#define SHARED_UNITBIT0_HIPART 0x43380000 + +typedef union _shared_wrappy +{ + double w_d; + int32 w_i[2]; +} t_shared_wrappy; + +typedef union _shared_floatint +{ + t_float fi_f; + int32 fi_i; +} t_shared_floatint; + +#define SHARED_TRUEBITS 0x3f800000 /* t_float f = 1; *(int32 *)&f */ + +#define SHARED_PI 3.14159265359 +#define SHARED_2PI 6.28318530718 + +#endif diff --git a/shared/sickle/Makefile b/shared/sickle/Makefile new file mode 100644 index 0000000..5dcb2c8 --- /dev/null +++ b/shared/sickle/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR = ../.. +include $(ROOT_DIR)/Makefile.common + +all: $(OBJECTS) diff --git a/shared/sickle/Makefile.objects b/shared/sickle/Makefile.objects new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/shared/sickle/Makefile.objects diff --git a/shared/sickle/Makefile.sources b/shared/sickle/Makefile.sources new file mode 100644 index 0000000..5575605 --- /dev/null +++ b/shared/sickle/Makefile.sources @@ -0,0 +1,3 @@ +OTHER_SOURCES = \ +sic.c \ +arsic.c diff --git a/shared/sickle/arsic.c b/shared/sickle/arsic.c new file mode 100644 index 0000000..8f0e309 --- /dev/null +++ b/shared/sickle/arsic.c @@ -0,0 +1,221 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* generic array-based signal class */ + +#include <stdio.h> +#include <string.h> +#include "m_pd.h" +#include "shared.h" +#include "common/vefl.h" +#include "sickle/sic.h" +#include "sickle/arsic.h" + +void arsic_clear(t_arsic *x) +{ + x->s_vecsize = 0; + memset(x->s_vectors, 0, x->s_nchannels * sizeof(*x->s_vectors)); +} + +void arsic_redraw(t_arsic *x) +{ + if (x->s_mononame) + { + t_garray *ap = + (t_garray *)pd_findbyclass(x->s_mononame, garray_class); + if (ap) garray_redraw(ap); + else if (x->s_vectors[0]) bug("arsic_redraw 1"); + } + else if (*x->s_stub) + { + int ch = x->s_nchannels; + while (ch--) + { + t_garray *ap = + (t_garray *)pd_findbyclass(x->s_channames[ch], garray_class); + if (ap) garray_redraw(ap); + else if (x->s_vectors[ch]) bug("arsic_redraw 2"); + } + } +} + +void arsic_validate(t_arsic *x, int complain) +{ + arsic_clear(x); + x->s_vecsize = SHARED_INT_MAX; + if (x->s_mononame) + { + x->s_vectors[0] = + vefl_get(x->s_mononame, &x->s_vecsize, 1, + (complain ? (t_pd *)x : 0)); + } + else if (*x->s_stub) + { + int ch; + for (ch = 0; ch < x->s_nchannels ; ch++) + { + int vsz = x->s_vecsize; /* ignore missing arrays */ + x->s_vectors[ch] = + vefl_get(x->s_channames[ch], &vsz, 1, + (complain ? (t_pd *)x : 0)); + if (vsz < x->s_vecsize) x->s_vecsize = vsz; + } + } + if (x->s_vecsize == SHARED_INT_MAX) x->s_vecsize = 0; +} + +void arsic_check(t_arsic *x) +{ + x->s_playable = (!((t_sic *)x)->s_disabled && x->s_vecsize >= x->s_minsize); +} + +int arsic_getnchannels(t_arsic *x) +{ + return (x->s_nchannels); +} + +void arsic_setarray(t_arsic *x, t_symbol *s, int complain) +{ + if (s) + { + if (x->s_mononame) x->s_mononame = s; + else + { + x->s_stub = s->s_name; + if (*x->s_stub) + { + char buf[MAXPDSTRING]; + int ch; + for (ch = 0; ch < x->s_nchannels; ch++) + { + sprintf(buf, "%d-%s", ch, x->s_stub); + x->s_channames[ch] = gensym(buf); + } + } + } + arsic_validate(x, complain); + } + arsic_check(x); +} + +void arsic_setminsize(t_arsic *x, int i) +{ + x->s_minsize = i; +} + +void arsic_dsp(t_arsic *x, t_signal **sp, t_perfroutine perf, int complain) +{ + t_int *ap = x->s_perfargs; + if (ap) + { + int i, nsigs = x->s_nperfargs - 2; + x->s_ksr = sp[0]->s_sr * 0.001; + arsic_validate(x, complain); + arsic_check(x); + + /* LATER consider glist traversing, and, if we have no feeders, + choosing an optimized version of perform routine */ + + *ap++ = (t_int)x; + *ap++ = (t_int)sp[0]->s_n; + for (i = 0; i < nsigs; i++) *ap++ = (t_int)sp[i]->s_vec; + dsp_addv(perf, x->s_nperfargs, x->s_perfargs); + } + else bug("arsic_dsp"); +} + +void arsic_free(t_arsic *x) +{ + if (x->s_vectors) + freebytes(x->s_vectors, x->s_nchannels * sizeof(*x->s_vectors)); + if (x->s_channames) + freebytes(x->s_channames, + x->s_nchannels * sizeof(*x->s_channames)); + if (x->s_perfargs) + freebytes(x->s_perfargs, x->s_nperfargs * sizeof(*x->s_perfargs)); +} + +/* If nauxsigs is positive, then the number of signals is nchannels + nauxsigs; + otherwise the channels are not used as signals, and the number of signals is + nsigs -- provided that nsigs is positive -- or, if it is not, then an arsic + is not used in dsp (peek~). */ +void *arsic_new(t_class *c, t_symbol *s, + int nchannels, int nsigs, int nauxsigs) +{ + t_arsic *x; + t_symbol *mononame; + char *stub; + t_float **vectors; + int nperfargs = 0; + t_int *perfargs = 0; + t_symbol **channames = 0; + if (!s) s = &s_; + if (nchannels < 1) + { + nchannels = 1; + mononame = s; + stub = 0; + } + else + { + mononame = 0; + stub = s->s_name; + } + if (!(vectors = (t_float **)getbytes(nchannels * sizeof(*vectors)))) + return (0); + if (nauxsigs > 0) + nperfargs = nchannels + nauxsigs + 2; + else if (nsigs > 0) + nperfargs = nsigs + 2; + if (nperfargs + && !(perfargs = (t_int *)getbytes(nperfargs * sizeof(*perfargs)))) + { + freebytes(vectors, nchannels * sizeof(*vectors)); + return (0); + } + if (stub && + !(channames = (t_symbol **)getbytes(nchannels * sizeof(*channames)))) + { + freebytes(vectors, nchannels * sizeof(*vectors)); + if (perfargs) freebytes(perfargs, nperfargs * sizeof(*perfargs)); + return (0); + } + x = (t_arsic *)pd_new(c); + x->s_vecsize = 0; + x->s_nchannels = nchannels; + x->s_vectors = vectors; + x->s_channames = channames; + x->s_nperfargs = nperfargs; + x->s_perfargs = perfargs; + x->s_mononame = mononame; + x->s_stub = stub; + x->s_ksr = sys_getsr() * 0.001; + ((t_sic *)x)->s_disabled = 0; + x->s_playable = 0; + x->s_minsize = 1; + arsic_setarray(x, s, 0); + return (x); +} + +static void arsic_enable(t_arsic *x, t_floatarg f) +{ + ((t_sic *)x)->s_disabled = (f == 0); + arsic_check(x); +} + +/* LATER somehow link this to sic_setup() */ +void arsic_setup(t_class *c, void *dspfn, void *floatfn) +{ + if (floatfn != SIC_NOMAINSIGNALIN) + { + if (floatfn) + { + class_domainsignalin(c, -1); + class_addfloat(c, floatfn); + } + else CLASS_MAINSIGNALIN(c, t_sic, s_f); + } + class_addmethod(c, (t_method)dspfn, gensym("dsp"), 0); + class_addmethod(c, (t_method)arsic_enable, gensym("enable"), 0); +} diff --git a/shared/sickle/arsic.h b/shared/sickle/arsic.h new file mode 100644 index 0000000..a941279 --- /dev/null +++ b/shared/sickle/arsic.h @@ -0,0 +1,38 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __ARSIC_H__ +#define __ARSIC_H__ + +typedef struct _arsic +{ + t_sic s_sic; + int s_vecsize; /* used also as a validation flag */ + int s_nchannels; + t_float **s_vectors; + t_symbol **s_channames; + int s_nperfargs; + t_int *s_perfargs; + t_symbol *s_mononame; /* used also as an 'ismono' flag */ + char *s_stub; + float s_ksr; + int s_playable; + int s_minsize; +} t_arsic; + +void arsic_clear(t_arsic *x); +void arsic_redraw(t_arsic *x); +void arsic_validate(t_arsic *x, int complain); +void arsic_check(t_arsic *x); +int arsic_getnchannels(t_arsic *x); +void arsic_setarray(t_arsic *x, t_symbol *s, int complain); +void arsic_setminsize(t_arsic *x, int i); + +void arsic_dsp(t_arsic *x, t_signal **sp, t_perfroutine perf, int complain); +void *arsic_new(t_class *c, t_symbol *s, + int nchannels, int nsigs, int nauxsigs); +void arsic_free(t_arsic *x); +void arsic_setup(t_class *c, void *dspfn, void *floatfn); + +#endif diff --git a/shared/sickle/sic.c b/shared/sickle/sic.c new file mode 100644 index 0000000..003120e --- /dev/null +++ b/shared/sickle/sic.c @@ -0,0 +1,119 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* generic signal class */ + +#include <math.h> +#include "m_pd.h" +#include "shared.h" +#include "common/loud.h" +#include "sickle/sic.h" + +//#define SIC_DEBUG + +#if defined(NT) || defined(MACOSX) +/* cf pd/src/x_arithmetic.c */ +#define cosf cos +#endif + +t_inlet *sic_inlet(t_sic *x, int ix, t_float df, int ax, int ac, t_atom *av) +{ + t_inlet *in = 0; + if (ax < ac) + { + if (av[ax].a_type == A_FLOAT) + df = av[ax].a_w.w_float; + else + loud_error((t_pd *)x, "bad argument %d (float expected)", ax + 1); + } + if (ix) + { + in = inlet_new((t_object *)x, (t_pd *)x, &s_signal, &s_signal); + /* this is persistent (in->i_un.iu_floatsignalvalue = df) */ + pd_float((t_pd *)in, df); + } + else + { + in = ((t_object *)x)->ob_inlet; + pd_float((t_pd *)x, df); + } + return (in); +} + +t_inlet *sic_newinlet(t_sic *x, t_float f) +{ + return (sic_inlet(x, 1, f, 0, 0, 0)); +} + +t_float *sic_makecostable(int *sizep) +{ + /* permanent cache (tables are never freed); LATER rethink */ + static t_float *sic_costables[SIC_NCOSTABLES]; + int ndx, sz; + /* round upwards -- always return at least requested number of elements, + unless the maximum of 2^SIC_NCOSTABLES is exceeded; LATER rethink */ + /* (the minimum, at ndx 0, is 2^1) */ + for (ndx = 0, sz = 2; ndx < (SIC_NCOSTABLES - 1); ndx++, sz <<= 1) + if (sz >= *sizep) + break; +#ifdef SIC_DEBUG + post("request for a costable of %d points (effective %d, ndx %d)", + *sizep, sz, ndx); +#endif + *sizep = sz; + if (sic_costables[ndx]) + return (sic_costables[ndx]); + else if (sz == COSTABSIZE && cos_table) + return (sic_costables[ndx] = cos_table); + else + { + int cnt = sz + 1; + float phase = 0, phsinc = SHARED_2PI / sz; + t_float *table = (t_float *)getbytes(cnt * sizeof(*table)), *tp = table; + if (table) + { +#ifdef SIC_DEBUG + post("got %d points of a costable", cnt); +#endif + while (cnt--) + { + *tp++ = cosf(phase); + phase += phsinc; + } + } + return (sic_costables[ndx] = table); + } +} + +static void sic_enable(t_sic *x, t_floatarg f) +{ + x->s_disabled = (f == 0); +} + +void sic_setup(t_class *c, void *dspfn, void *floatfn) +{ + static int checked = 0; + if (!checked) + { + /* MSP: here we check at startup whether the byte alignment + is as we declared it. If not, the code has to be + recompiled the other way. */ + t_shared_wrappy wrappy; + wrappy.w_d = SHARED_UNITBIT32 + 0.5; + if ((unsigned)wrappy.w_i[SHARED_LOWOFFSET] != 0x80000000) + bug("sic_setup: unexpected machine alignment"); + checked = 1; + } + if (floatfn != SIC_NOMAINSIGNALIN) + { + if (floatfn) + { + class_domainsignalin(c, -1); + class_addfloat(c, floatfn); + } + else CLASS_MAINSIGNALIN(c, t_sic, s_f); + } + class_addmethod(c, (t_method)dspfn, gensym("dsp"), 0); + class_addmethod(c, (t_method)sic_enable, gensym("enable"), 0); +} diff --git a/shared/sickle/sic.h b/shared/sickle/sic.h new file mode 100644 index 0000000..9dce95f --- /dev/null +++ b/shared/sickle/sic.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __SIC_H__ +#define __SIC_H__ + +typedef struct _sic +{ + t_object s_ob; + t_float s_f; + int s_disabled; +} t_sic; + +#define SIC_FLOATTOSIGNAL ((void *)0) +#define SIC_NOMAINSIGNALIN ((void *)-1) + +#define SIC_NCOSTABLES 16 /* this is oscbank~'s max, LATER rethink */ + +t_inlet *sic_inlet(t_sic *x, int ix, t_float df, int ax, int ac, t_atom *av); +t_inlet *sic_newinlet(t_sic *x, t_float f); +t_float *sic_makecostable(int *sizep); +void sic_setup(t_class *c, void *dspfn, void *floatfn); + +#endif diff --git a/shared/unstable/Makefile b/shared/unstable/Makefile new file mode 100644 index 0000000..5dcb2c8 --- /dev/null +++ b/shared/unstable/Makefile @@ -0,0 +1,4 @@ +ROOT_DIR = ../.. +include $(ROOT_DIR)/Makefile.common + +all: $(OBJECTS) diff --git a/shared/unstable/Makefile.objects b/shared/unstable/Makefile.objects new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/shared/unstable/Makefile.objects diff --git a/shared/unstable/Makefile.sources b/shared/unstable/Makefile.sources new file mode 100644 index 0000000..4636701 --- /dev/null +++ b/shared/unstable/Makefile.sources @@ -0,0 +1,4 @@ +OTHER_SOURCES = \ +fragile.c \ +forky.c \ +loader.c diff --git a/shared/unstable/forky.c b/shared/unstable/forky.c new file mode 100644 index 0000000..7fb6b08 --- /dev/null +++ b/shared/unstable/forky.c @@ -0,0 +1,56 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include "m_pd.h" +#include "g_canvas.h" +#include "shared.h" +#include "unstable/forky.h" + +//#define FORKY_DEBUG + +/* To be called in a 'dsp' method -- e.g. if there are no feeders, the caller + might use an optimized version of a 'perform' routine. + LATER think about replacing 'linetraverser' calls with something faster. */ +int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym) +{ + t_linetraverser t; + linetraverser_start(&t, glist); + while (linetraverser_next(&t)) + if (t.tr_ob2 == x && t.tr_inno == inno +#ifdef PD_VERSION /* FIXME ask Miller */ + && (!outsym || outsym == outlet_getsymbol(t.tr_outlet)) +#endif + ) + return (1); + return (0); +} + +/* Not really a forky, just found no better place to put it in. + Used in bitwise signal binops (sickle). Checked against msp2. */ +t_int forky_getbitmask(int ac, t_atom *av) +{ + t_int result = 0; + if (sizeof(shared_t_bitmask) >= sizeof(t_int)) + { + int nbits = sizeof(t_int) * 8; + shared_t_bitmask bitmask = 1 << (nbits - 1); + if (ac > nbits) + ac = nbits; + while (ac--) + { + if (av->a_type == A_FLOAT && + (int)av->a_w.w_float) /* CHECKED */ + result |= bitmask; + /* CHECKED symbols are zero */ + bitmask >>= 1; + av++; + } + /* CHECKED missing are zero */ +#ifdef FORKY_DEBUG + post("mask set to %.8x", result); +#endif + } + else bug("sizeof(shared_t_bitmask)"); + return (result); +} diff --git a/shared/unstable/forky.h b/shared/unstable/forky.h new file mode 100644 index 0000000..0d27080 --- /dev/null +++ b/shared/unstable/forky.h @@ -0,0 +1,11 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __FORKY_H__ +#define __FORKY_H__ + +int forky_hasfeeders(t_object *x, t_glist *glist, int inno, t_symbol *outsym); +t_int forky_getbitmask(int ac, t_atom *av); + +#endif diff --git a/shared/unstable/fragile.c b/shared/unstable/fragile.c new file mode 100644 index 0000000..3267721 --- /dev/null +++ b/shared/unstable/fragile.c @@ -0,0 +1,67 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#include <string.h> +#include "m_pd.h" +#include "unstable/pd_imp.h" +#include "unstable/fragile.h" + +int fragile_class_count(void) +{ + return (pd_objectmaker->c_nmethod); +} + +void fragile_class_printnames(char *msg, int firstndx, int lastndx) +{ + t_methodentry *mp = pd_objectmaker->c_methods; + int ndx, len = strlen(msg); + startpost(msg); + for (ndx = firstndx, mp += ndx; ndx <= lastndx; ndx++, mp++) + { + t_symbol *s = mp->me_name; + if (s && s->s_name[0] != '_') + { + int l = 1 + strlen(s->s_name); + if ((len += l) > 66) + { + endpost(); + startpost(" "); + len = 3 + l; + } + poststring(s->s_name); + } + } + endpost(); +} + +/* This structure is local to g_array.c. We need it, + because there is no other way to get into array's graph. */ +struct _garray +{ + t_gobj x_gobj; + t_glist *x_glist; + /* ... */ +}; + +t_glist *fragile_garray_glist(void *arr) +{ + return (((struct _garray *)arr)->x_glist); +} + +/* This is local to m_obj.c. + LATER export write access to o_connections field ('grab' class). + LATER encapsulate 'traverseoutlet' routines (not in the stable API yet). */ +struct _outlet +{ + t_object *o_owner; + struct _outlet *o_next; + t_outconnect *o_connections; + t_symbol *o_sym; +}; + +/* obj_starttraverseoutlet() replacement */ +t_outconnect *fragile_outlet_connections(t_outlet *o) +{ + return (o ? o->o_connections : 0); +} diff --git a/shared/unstable/fragile.h b/shared/unstable/fragile.h new file mode 100644 index 0000000..c1ba8e3 --- /dev/null +++ b/shared/unstable/fragile.h @@ -0,0 +1,13 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __FRAGILE_H__ +#define __FRAGILE_H__ + +int fragile_class_count(void); +void fragile_class_printnames(char *msg, int firstndx, int lastndx); +t_glist *fragile_garray_glist(void *arr); +t_outconnect *fragile_outlet_connections(t_outlet *o); + +#endif diff --git a/shared/unstable/loader.c b/shared/unstable/loader.c new file mode 100644 index 0000000..91b7ff3 --- /dev/null +++ b/shared/unstable/loader.c @@ -0,0 +1,139 @@ +/* Copyright (c) 1997-2003 Miller Puckette, krzYszcz, and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* This is just a not-yet-in-the-API-sys_load_lib() duplication + (modulo differentiating the error return codes). LATER use the original. */ + +#include "loader.h" + +#ifdef __linux__ +#include <dlfcn.h> +#endif +#ifdef UNIX +#include <stdlib.h> +#include <unistd.h> +#endif +#ifdef NT +#include <io.h> +#include <windows.h> +#endif +#ifdef MACOSX +#include <mach-o/dyld.h> +#endif +#include <string.h> +#include "m_pd.h" +#include <stdio.h> + +typedef void (*t_xxx)(void); + +static char sys_dllextent[] = +#ifdef __FreeBSD__ + ".pd_freebsd"; +#endif +#ifdef IRIX +#ifdef N32 + ".pd_irix6"; +#else + ".pd_irix5"; +#endif +#endif +#ifdef __linux__ + ".pd_linux"; +#endif +#ifdef MACOSX + ".pd_darwin"; +#endif +#ifdef NT + ".dll"; +#endif + +int unstable_load_lib(char *dirname, char *classname) +{ + char symname[MAXPDSTRING], filename[MAXPDSTRING], dirbuf[MAXPDSTRING], + *nameptr, *lastdot; + void *dlobj; + t_xxx makeout; + int fd; +#ifdef NT + HINSTANCE ntdll; +#endif +#if 0 + fprintf(stderr, "lib %s %s\n", dirname, classname); +#endif + if ((fd = open_via_path(dirname, classname, sys_dllextent, + dirbuf, &nameptr, MAXPDSTRING, 1)) < 0) + { + return (LOADER_NOFILE); + } + else + { + close(fd); + /* refabricate the pathname */ + strcpy(filename, dirbuf); + strcat(filename, "/"); + strcat(filename, nameptr); + /* extract the setup function name */ + if (lastdot = strrchr(nameptr, '.')) + *lastdot = 0; + +#ifdef MACOSX + strcpy(symname, "_"); + strcat(symname, nameptr); +#else + strcpy(symname, nameptr); +#endif + /* if the last character is a tilde, replace with "_tilde" */ + if (symname[strlen(symname) - 1] == '~') + strcpy(symname + (strlen(symname) - 1), "_tilde"); + /* and append _setup to form the C setup function name */ + strcat(symname, "_setup"); +#ifdef __linux__ + dlobj = dlopen(filename, RTLD_NOW | RTLD_GLOBAL); + if (!dlobj) + { + post("%s: %s", filename, dlerror()); + return (LOADER_BADFILE); + } + makeout = (t_xxx)dlsym(dlobj, symname); +#endif +#ifdef NT + sys_bashfilename(filename, filename); + ntdll = LoadLibrary(filename); + if (!ntdll) + { + post("%s: couldn't load", filename); + return (LOADER_BADFILE); + } + makeout = (t_xxx)GetProcAddress(ntdll, symname); +#endif +#ifdef MACOSX + { + NSObjectFileImage image; + void *ret; + NSSymbol s; + if ( NSCreateObjectFileImageFromFile( filename, &image) != NSObjectFileImageSuccess ) + { + post("%s: couldn't load", filename); + return (LOADER_BADFILE); + } + ret = NSLinkModule( image, filename, + NSLINKMODULE_OPTION_BINDNOW + + NSLINKMODULE_OPTION_PRIVATE); + + s = NSLookupSymbolInModule(ret, symname); + + if (s) + makeout = (t_xxx)NSAddressOfSymbol( s); + else makeout = 0; + } +#endif + } + if (!makeout) + { + post("load_object: Symbol \"%s\" not found", symname); + return (LOADER_NOENTRY); + } + (*makeout)(); + return (LOADER_OK); +} diff --git a/shared/unstable/loader.h b/shared/unstable/loader.h new file mode 100644 index 0000000..e9766ac --- /dev/null +++ b/shared/unstable/loader.h @@ -0,0 +1,12 @@ +/* Copyright (c) 2003 krzYszcz and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __LOADER_H__ +#define __LOADER_H__ + +enum { LOADER_OK, LOADER_NOFILE, LOADER_BADFILE, LOADER_NOENTRY }; + +int unstable_load_lib(char *dirname, char *classname); + +#endif diff --git a/shared/unstable/pd_imp.h b/shared/unstable/pd_imp.h new file mode 100644 index 0000000..bf659ed --- /dev/null +++ b/shared/unstable/pd_imp.h @@ -0,0 +1,60 @@ +/* Copyright (c) 1997-2003 Miller Puckette and others. + * For information on usage and redistribution, and for a DISCLAIMER OF ALL + * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +#ifndef __PD_IMP_H__ +#define __PD_IMP_H__ + +#ifdef PD_MINOR_VERSION +#include "m_imp.h" +#else + +typedef struct _methodentry +{ + t_symbol *me_name; + t_gotfn me_fun; + t_atomtype me_arg[MAXPDARG+1]; +} t_methodentry; + +EXTERN_STRUCT _widgetbehavior; + +typedef void (*t_bangmethod)(t_pd *x); +typedef void (*t_pointermethod)(t_pd *x, t_gpointer *gp); +typedef void (*t_floatmethod)(t_pd *x, t_float f); +typedef void (*t_symbolmethod)(t_pd *x, t_symbol *s); +typedef void (*t_listmethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); +typedef void (*t_anymethod)(t_pd *x, t_symbol *s, int argc, t_atom *argv); + +struct _class +{ + t_symbol *c_name; /* name (mostly for error reporting) */ + t_symbol *c_helpname; /* name of help file */ + size_t c_size; /* size of an instance */ + t_methodentry *c_methods; /* methods other than bang, etc below */ + int c_nmethod; /* number of methods */ + t_method c_freemethod; /* function to call before freeing */ + t_bangmethod c_bangmethod; /* common methods */ + t_pointermethod c_pointermethod; + t_floatmethod c_floatmethod; + t_symbolmethod c_symbolmethod; + t_listmethod c_listmethod; + t_anymethod c_anymethod; + struct _widgetbehavior *c_wb; /* "gobjs" only */ + struct _parentwidgetbehavior *c_pwb;/* widget behavior in parent */ + int c_floatsignalin; /* onset to float for signal input */ + char c_gobj; /* true if is a gobj */ + char c_patchable; /* true if we have a t_object header */ + char c_firstin; /* if patchable, true if draw first inlet */ + char c_drawcommand; /* a drawing command for a template */ +}; + +EXTERN int obj_noutlets(t_object *x); +EXTERN int obj_ninlets(t_object *x); +EXTERN t_outconnect *obj_starttraverseoutlet(t_object *x, t_outlet **op, + int nout); +EXTERN t_outconnect *obj_nexttraverseoutlet(t_outconnect *lastconnect, + t_object **destp, t_inlet **inletp, int *whichp); + +#endif + +#endif diff --git a/test/cyclone/Borax-test.pd b/test/cyclone/Borax-test.pd new file mode 100644 index 0000000..aa2970b --- /dev/null +++ b/test/cyclone/Borax-test.pd @@ -0,0 +1,120 @@ +#N canvas 137 29 642 442 12; +#X obj 24 185 Borax dummy; +#X floatatom 24 220 5 0 0; +#X floatatom 24 124 5 0 0; +#X msg 24 86 1; +#X msg 80 86 0; +#X msg 118 152 bang; +#X obj 129 86 counter; +#X msg 57 51 set 0; +#X msg 129 18 128; +#X obj 129 51 Uzi; +#X obj 326 220 Borax dummy; +#X obj 469 324 funbuff; +#C restore; +#X obj 230 324 funbuff; +#C restore; +#X obj 356 324 funbuff; +#C restore; +#X obj 326 185 makenote; +#X obj 326 86 random 128; +#X obj 393 152 random 1000; +#X obj 326 51 t b b b; +#X msg 326 18 bang; +#X msg 209 220 dump; +#X obj 230 359 pack; +#X obj 230 392 print pitch; +#X obj 469 359 pack; +#X obj 469 392 print delta; +#X obj 356 359 pack; +#X obj 356 392 print dur; +#X msg 260 220 dump; +#X msg 486 220 dump; +#X msg 230 263 clear; +#X obj 356 288 spigot; +#X msg 405 263 1; +#X msg 419 288 0; +#X obj 469 288 spigot; +#X msg 518 263 1; +#X msg 532 288 0; +#X obj 92 220 print voice; +#X obj 210 86 urn 128; +#X msg 210 18 128; +#X obj 210 51 Uzi; +#X msg 258 51 clear; +#X msg 536 18 128; +#X obj 411 51 Uzi; +#X msg 420 185 bang; +#X obj 456 51 t b b b; +#X obj 456 86 urn 128; +#X obj 514 152 random 1000; +#X msg 536 51 clear; +#X obj 456 18 t 0 b; +#X msg 485 119 64; +#X msg 355 119 64; +#X connect 0 0 1 0; +#X connect 0 1 35 0; +#X connect 2 0 0 0; +#X connect 3 0 0 1; +#X connect 4 0 0 1; +#X connect 5 0 0 2; +#X connect 6 0 0 0; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 9 0 6 0; +#X connect 10 0 12 0; +#X connect 10 0 32 0; +#X connect 10 0 29 0; +#X connect 10 3 12 1; +#X connect 10 6 13 1; +#X connect 10 6 30 0; +#X connect 10 8 11 1; +#X connect 10 8 33 0; +#X connect 11 0 22 0; +#X connect 11 1 22 1; +#X connect 12 0 20 0; +#X connect 12 1 20 1; +#X connect 13 0 24 0; +#X connect 13 1 24 1; +#X connect 14 0 10 0; +#X connect 14 1 10 1; +#X connect 15 0 14 0; +#X connect 16 0 14 2; +#X connect 17 0 15 0; +#X connect 17 1 49 0; +#X connect 17 2 16 0; +#X connect 18 0 17 0; +#X connect 19 0 12 0; +#X connect 20 0 21 0; +#X connect 22 0 23 0; +#X connect 24 0 25 0; +#X connect 26 0 13 0; +#X connect 27 0 11 0; +#X connect 28 0 12 0; +#X connect 28 0 13 0; +#X connect 28 0 11 0; +#X connect 29 0 31 0; +#X connect 29 0 13 0; +#X connect 30 0 29 1; +#X connect 31 0 29 1; +#X connect 32 0 34 0; +#X connect 32 0 11 0; +#X connect 33 0 32 1; +#X connect 34 0 32 1; +#X connect 36 0 0 0; +#X connect 37 0 38 0; +#X connect 38 0 36 0; +#X connect 39 0 36 0; +#X connect 40 0 47 0; +#X connect 41 0 43 0; +#X connect 42 0 10 2; +#X connect 43 0 44 0; +#X connect 43 1 48 0; +#X connect 43 2 45 0; +#X connect 44 0 14 0; +#X connect 45 0 14 2; +#X connect 46 0 44 0; +#X connect 47 0 41 0; +#X connect 47 1 46 0; +#X connect 48 0 14 1; +#X connect 49 0 14 1; diff --git a/test/cyclone/Bucket-test.pd b/test/cyclone/Bucket-test.pd new file mode 100644 index 0000000..c43b0ed --- /dev/null +++ b/test/cyclone/Bucket-test.pd @@ -0,0 +1,40 @@ +#N canvas 306 219 459 482 12; +#X obj 134 126 Bucket 10 padding; +#X floatatom 134 433 5 0 0; +#X floatatom 150 403 5 0 0; +#X floatatom 166 374 5 0 0; +#X floatatom 183 343 5 0 0; +#X floatatom 199 313 5 0 0; +#X floatatom 216 282 5 0 0; +#X floatatom 232 255 5 0 0; +#X floatatom 249 224 5 0 0; +#X floatatom 265 192 5 0 0; +#X floatatom 282 162 5 0 0; +#X msg 233 21 roll; +#X floatatom 232 56 5 0 0; +#X msg 232 88 set \$1; +#X floatatom 81 56 5 0 0; +#X msg 156 21 l2r; +#X msg 156 56 r2l; +#X msg 332 56 freeze; +#X msg 332 88 thaw; +#X msg 21 56 bang; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 0 2 3 0; +#X connect 0 3 4 0; +#X connect 0 4 5 0; +#X connect 0 5 6 0; +#X connect 0 6 7 0; +#X connect 0 7 8 0; +#X connect 0 8 9 0; +#X connect 0 9 10 0; +#X connect 11 0 0 0; +#X connect 12 0 13 0; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 15 0 0 0; +#X connect 16 0 0 0; +#X connect 17 0 0 0; +#X connect 18 0 0 0; +#X connect 19 0 0 0; diff --git a/test/cyclone/Decode-test.pd b/test/cyclone/Decode-test.pd new file mode 100644 index 0000000..bd35b61 --- /dev/null +++ b/test/cyclone/Decode-test.pd @@ -0,0 +1,18 @@ +#N canvas 314 293 450 300 12; +#X obj 151 134 Decode 4; +#X obj 151 256 print a; +#X obj 173 230 print b; +#X obj 195 200 print c; +#X obj 218 172 print d; +#X floatatom 68 81 5 0 0; +#X obj 184 81 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 218 81 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 0 2 3 0; +#X connect 0 3 4 0; +#X connect 5 0 0 0; +#X connect 6 0 0 1; +#X connect 7 0 0 2; diff --git a/test/cyclone/Histo-test.pd b/test/cyclone/Histo-test.pd new file mode 100644 index 0000000..cd22730 --- /dev/null +++ b/test/cyclone/Histo-test.pd @@ -0,0 +1,20 @@ +#N canvas 386 259 450 300 12; +#X obj 158 150 Histo 1000; +#X obj 158 226 print a; +#X obj 243 226 print b; +#X msg 51 93 bang; +#X msg 158 93 700; +#X msg 111 93 -1; +#X msg 243 44 1000; +#X msg 263 93 700.5; +#X msg 178 121 clear; +#X msg 139 44 1 1; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 1; +#X connect 7 0 0 1; +#X connect 8 0 0 0; +#X connect 9 0 0 0; diff --git a/test/cyclone/MouseState-test.pd b/test/cyclone/MouseState-test.pd new file mode 100644 index 0000000..12b13ff --- /dev/null +++ b/test/cyclone/MouseState-test.pd @@ -0,0 +1,54 @@ +#N canvas 228 259 751 304 12; +#X obj 179 129 MouseState; +#X obj 179 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X floatatom 200 238 5 0 0 0 - - -; +#X floatatom 221 213 5 0 0 0 - - -; +#X floatatom 242 185 5 0 0 0 - - -; +#X floatatom 264 159 5 0 0 0 - - -; +#X obj 179 19 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 179 54 metro 50; +#X msg 272 54 zero; +#X msg 272 86 reset; +#X msg 35 87 poll; +#X msg 99 87 nopoll; +#X obj 523 129 MouseState; +#X obj 523 264 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X floatatom 544 238 5 0 0 0 - - -; +#X floatatom 565 213 5 0 0 0 - - -; +#X floatatom 586 185 5 0 0 0 - - -; +#X floatatom 608 159 5 0 0 0 - - -; +#X obj 523 19 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 523 54 metro 50; +#X msg 616 54 zero; +#X msg 616 86 reset; +#X msg 379 87 poll; +#X msg 443 87 nopoll; +#X obj 53 213 capture; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 0 1 24 0; +#X connect 0 2 3 0; +#X connect 0 2 24 0; +#X connect 0 3 4 0; +#X connect 0 4 5 0; +#X connect 6 0 7 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 0 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 13 0; +#X connect 12 1 14 0; +#X connect 12 2 15 0; +#X connect 12 3 16 0; +#X connect 12 4 17 0; +#X connect 18 0 19 0; +#X connect 19 0 12 0; +#X connect 20 0 12 0; +#X connect 21 0 12 0; +#X connect 22 0 12 0; +#X connect 23 0 12 0; diff --git a/test/cyclone/TogEdge-test.pd b/test/cyclone/TogEdge-test.pd new file mode 100644 index 0000000..9198075 --- /dev/null +++ b/test/cyclone/TogEdge-test.pd @@ -0,0 +1,16 @@ +#N canvas 516 361 368 289 12; +#X obj 109 129 TogEdge; +#X obj 109 184 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 167 184 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 168 74 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 109 74 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X msg 36 74 1.5; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; diff --git a/test/cyclone/Uzi-test.pd b/test/cyclone/Uzi-test.pd new file mode 100644 index 0000000..c01ad33 --- /dev/null +++ b/test/cyclone/Uzi-test.pd @@ -0,0 +1,27 @@ +#N canvas 407 221 414 285 12; +#X obj 153 97 Uzi; +#X obj 153 194 counter; +#X floatatom 153 225 5 0 0; +#X msg 153 35 bang; +#X msg 212 35 99; +#X msg 212 66 11; +#X floatatom 336 171 5 0 0; +#X msg 62 225 pause; +#X msg 55 35 resume; +#X obj 296 136 t 0 0; +#X obj 62 194 sel 10; +#X floatatom 267 77 5 0 0; +#X obj 164 136 print carry; +#X connect 0 0 1 0; +#X connect 0 1 12 0; +#X connect 0 2 9 0; +#X connect 1 0 2 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 1; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 10 0; +#X connect 9 1 6 0; +#X connect 10 0 7 0; +#X connect 11 0 0 1; diff --git a/test/cyclone/active-test.pd b/test/cyclone/active-test.pd new file mode 100644 index 0000000..6f40f96 --- /dev/null +++ b/test/cyclone/active-test.pd @@ -0,0 +1,19 @@ +#N canvas 52 81 262 185 12; +#X obj 27 29 active; +#X obj 27 74 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X obj 129 29 active; +#X obj 129 74 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#N canvas 376 80 255 181 test 1; +#X obj 27 29 active; +#X obj 27 74 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 129 29 active; +#X obj 129 74 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X connect 0 0 1 0; +#X connect 2 0 3 0; +#X restore 31 138 pd test; +#X connect 0 0 1 0; +#X connect 2 0 3 0; diff --git a/test/cyclone/anal-test.pd b/test/cyclone/anal-test.pd new file mode 100644 index 0000000..a4ec7ab --- /dev/null +++ b/test/cyclone/anal-test.pd @@ -0,0 +1,17 @@ +#N canvas 466 161 450 300 12; +#X obj 62 215 print; +#X msg 62 67 1; +#X floatatom 119 67 5 0 0; +#X msg 189 67 reset; +#X msg 189 108 clear; +#X obj 198 215 anal 1025; +#X obj 62 167 anal; +#X msg 118 27 128 \, -1; +#X msg 203 27 1.1; +#X connect 1 0 6 0; +#X connect 2 0 6 0; +#X connect 3 0 6 0; +#X connect 4 0 6 0; +#X connect 6 0 0 0; +#X connect 7 0 6 0; +#X connect 8 0 6 0; diff --git a/test/cyclone/append-test.pd b/test/cyclone/append-test.pd new file mode 100644 index 0000000..821c22e --- /dev/null +++ b/test/cyclone/append-test.pd @@ -0,0 +1,78 @@ +#N canvas 516 251 510 466 12; +#X obj 25 416 print; +#X msg 25 298 1 2 3; +#X msg 102 298 set test; +#X obj 25 241 print; +#X msg 25 51 1 2 3; +#X obj 25 169 t a b; +#X msg 111 241 4 5 6; +#X obj 190 206 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 347 50 testmess 1000; +#X msg 347 19 mess; +#X msg 101 19 mess; +#X obj 101 50 testmess 100; +#X msg 155 128 set changed; +#X obj 111 169 gate; +#X obj 111 206 t b b; +#X obj 25 377 t a b b; +#X msg 220 416 set mess1; +#X msg 108 416 set mess2; +#X msg 285 241 bang; +#X msg 347 241 99; +#X obj 285 377 print list; +#X obj 285 339 route list; +#X obj 408 377 print; +#X msg 227 241 mess; +#X msg 398 241 set bang; +#X msg 400 278 set 0; +#X obj 101 81 prepend check; +#X msg 160 19 set set; +#X msg 244 19 set check; +#X obj 25 128 Append test; +#X obj 25 339 Append test; +#X obj 285 298 Append; +#X obj 347 81 prepend check; +#X msg 398 206 set test; +#X obj 301 159 Append test it; +#X obj 301 190 print; +#X msg 301 128 symbol mess; +#X connect 1 0 30 0; +#X connect 2 0 30 0; +#X connect 4 0 29 0; +#X connect 5 0 3 0; +#X connect 5 1 13 1; +#X connect 6 0 29 0; +#X connect 7 0 13 0; +#X connect 8 0 32 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 11 0 26 0; +#X connect 12 0 29 0; +#X connect 13 0 14 0; +#X connect 14 0 6 0; +#X connect 14 1 7 0; +#X connect 15 0 0 0; +#X connect 15 1 17 0; +#X connect 15 2 16 0; +#X connect 16 0 30 0; +#X connect 17 0 30 0; +#X connect 18 0 31 0; +#X connect 19 0 31 0; +#X connect 21 0 20 0; +#X connect 21 1 22 0; +#X connect 23 0 31 0; +#X connect 24 0 31 0; +#X connect 25 0 31 0; +#X connect 26 0 29 0; +#X connect 27 0 26 0; +#X connect 27 0 32 0; +#X connect 28 0 26 0; +#X connect 28 0 32 0; +#X connect 29 0 5 0; +#X connect 30 0 15 0; +#X connect 31 0 21 0; +#X connect 32 0 29 0; +#X connect 33 0 31 0; +#X connect 34 0 35 0; +#X connect 36 0 34 0; diff --git a/test/cyclone/bad.coll b/test/cyclone/bad.coll new file mode 100644 index 0000000..bb76cf7 --- /dev/null +++ b/test/cyclone/bad.coll @@ -0,0 +1,4 @@ +11, testing coll; +12, missing semi +13 extra key, with data; +14 empty,; diff --git a/test/cyclone/bondo-test.pd b/test/cyclone/bondo-test.pd new file mode 100644 index 0000000..38a43ba --- /dev/null +++ b/test/cyclone/bondo-test.pd @@ -0,0 +1,73 @@ +#N canvas 289 274 747 476 12; +#X obj 78 164 print first; +#X obj 199 165 print last; +#X msg 78 22 any message; +#X msg 199 21 other message; +#X msg 94 62 11; +#X msg 211 62 55; +#X obj 78 108 bondo 5 1000 n; +#X obj 412 203 print first; +#X obj 530 169 print last; +#X msg 412 22 any message; +#X msg 533 57 other message; +#X msg 437 92 11; +#X msg 545 92 55; +#X obj 412 133 bondo 5 1000; +#X obj 437 169 print 2nd; +#X msg 429 57 1 2 3; +#X msg 21 62 test; +#X msg 356 92 test; +#X obj 78 390 print first; +#X obj 199 391 print last; +#X msg 78 248 any message; +#X msg 199 247 other message; +#X msg 94 288 11; +#X msg 211 288 55; +#X obj 412 429 print first; +#X obj 530 395 print last; +#X msg 412 248 any message; +#X msg 533 283 other message; +#X msg 437 318 11; +#X msg 528 318 55; +#X obj 437 395 print 2nd; +#X msg 429 283 1 2 3; +#X msg 21 288 test; +#X msg 356 318 test; +#X obj 78 334 bondo 5 n; +#X obj 412 359 bondo 5; +#X msg 583 319 -1 -2 \, -2 -3; +#X msg 600 92 -1 -2 \, -2 -3; +#X connect 2 0 6 0; +#X connect 3 0 6 4; +#X connect 4 0 6 0; +#X connect 5 0 6 4; +#X connect 6 0 0 0; +#X connect 6 4 1 0; +#X connect 9 0 13 0; +#X connect 10 0 13 4; +#X connect 11 0 13 0; +#X connect 12 0 13 4; +#X connect 13 0 7 0; +#X connect 13 1 14 0; +#X connect 13 4 8 0; +#X connect 15 0 13 0; +#X connect 16 0 6 0; +#X connect 17 0 13 0; +#X connect 20 0 34 0; +#X connect 21 0 34 4; +#X connect 22 0 34 0; +#X connect 23 0 34 4; +#X connect 26 0 35 0; +#X connect 27 0 35 4; +#X connect 28 0 35 0; +#X connect 29 0 35 4; +#X connect 31 0 35 0; +#X connect 32 0 34 0; +#X connect 33 0 35 0; +#X connect 34 0 18 0; +#X connect 34 4 19 0; +#X connect 35 0 24 0; +#X connect 35 1 30 0; +#X connect 35 4 25 0; +#X connect 36 0 35 3; +#X connect 37 0 13 3; diff --git a/test/cyclone/buddy-test.pd b/test/cyclone/buddy-test.pd new file mode 100644 index 0000000..3c072b1 --- /dev/null +++ b/test/cyclone/buddy-test.pd @@ -0,0 +1,28 @@ +#N canvas 242 401 623 363 12; +#X obj 66 268 print a; +#X obj 168 268 print b; +#X floatatom 107 83 5 0 0; +#X floatatom 264 184 5 0 0; +#X msg 136 116 symbol test1; +#X msg 264 152 symbol test2; +#X msg 264 77 one two three; +#X msg 264 116 1 2 3 4 5 6 7 8 9; +#X msg 38 25 a long message with floats 1 2 3 4 5 6 7 8 9 (lets make +it even longer); +#X obj 260 268 print c; +#X obj 139 212 buddy 3; +#X msg 40 156 clear; +#X connect 2 0 10 0; +#X connect 2 0 10 1; +#X connect 3 0 10 2; +#X connect 4 0 10 0; +#X connect 4 0 10 1; +#X connect 5 0 10 2; +#X connect 6 0 10 2; +#X connect 7 0 10 2; +#X connect 8 0 10 0; +#X connect 8 0 10 1; +#X connect 10 0 0 0; +#X connect 10 1 1 0; +#X connect 10 2 9 0; +#X connect 11 0 10 0; diff --git a/test/cyclone/capture-test.pd b/test/cyclone/capture-test.pd new file mode 100644 index 0000000..0ebc045 --- /dev/null +++ b/test/cyclone/capture-test.pd @@ -0,0 +1,48 @@ +#N canvas 548 272 562 363 12; +#X obj 81 169 capture; +#X obj 169 169 capture 100000; +#X obj 169 216 print; +#X floatatom 81 96 5 0 0 0 - - -; +#X floatatom 169 96 5 0 0 0 - - -; +#X obj 323 169 capture 2; +#X obj 431 169 capture 1; +#X floatatom 323 96 5 0 0 0 - - -; +#X floatatom 431 96 5 0 0 0 - - -; +#X msg 242 96 wclose; +#X msg 59 59 write; +#X msg 266 59 write test.capture; +#X msg 16 96 dump; +#X msg 147 24 1 2 3 4 5 6 7 8 9; +#X msg 133 59 clear; +#X msg 500 96 dump; +#X msg 500 128 count; +#X msg 376 134 count; +#X obj 265 297 capture 10 x; +#X obj 402 297 capture 10 m; +#X floatatom 347 243 5 0 0 0 - - -; +#X msg 226 134 count; +#X msg 250 243 write; +#X connect 0 0 2 0; +#X connect 1 0 2 0; +#X connect 3 0 0 0; +#X connect 4 0 1 0; +#X connect 5 0 2 0; +#X connect 6 0 2 0; +#X connect 7 0 5 0; +#X connect 8 0 6 0; +#X connect 9 0 0 0; +#X connect 9 0 1 0; +#X connect 9 0 5 0; +#X connect 9 0 6 0; +#X connect 10 0 0 0; +#X connect 11 0 1 0; +#X connect 12 0 0 0; +#X connect 13 0 1 0; +#X connect 14 0 1 0; +#X connect 15 0 6 0; +#X connect 16 0 6 0; +#X connect 17 0 5 0; +#X connect 20 0 18 0; +#X connect 20 0 19 0; +#X connect 21 0 1 0; +#X connect 22 0 18 0; diff --git a/test/cyclone/click-test.pd b/test/cyclone/click-test.pd new file mode 100644 index 0000000..3a16ae6 --- /dev/null +++ b/test/cyclone/click-test.pd @@ -0,0 +1,26 @@ +#N canvas 480 212 450 300 12; +#X obj 45 136 click~; +#X obj 247 136 click~ -1; +#X obj 45 59 testmess 100; +#X msg 45 24 bang; +#X obj 45 98 prepend set; +#X obj 68 237 capture~ f; +#X msg 68 207 clear; +#X obj 212 237 capture~ f; +#X msg 212 207 clear; +#X msg 176 98 bang; +#X msg 182 24 bang; +#X obj 182 59 testmess 1000; +#X connect 0 0 5 0; +#X connect 1 0 7 0; +#X connect 2 0 4 0; +#X connect 3 0 2 0; +#X connect 4 0 0 0; +#X connect 6 0 5 0; +#X connect 8 0 7 0; +#X connect 9 0 0 0; +#X connect 9 0 1 0; +#X connect 9 0 6 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 11 0 4 0; diff --git a/test/cyclone/clip-test.pd b/test/cyclone/clip-test.pd new file mode 100644 index 0000000..9bc83ef --- /dev/null +++ b/test/cyclone/clip-test.pd @@ -0,0 +1,41 @@ +#N canvas 282 194 586 335 12; +#X obj 32 223 Clip -5; +#X obj 32 255 print; +#X msg 32 176 set test; +#X msg 122 175 set test -5; +#X floatatom 46 103 5 0 0; +#X msg 122 143 set test 3; +#X msg 58 143 set; +#X obj 406 234 Clip -5 0; +#X obj 406 266 print; +#X msg 427 207 set; +#X msg 406 176 set -5; +#X floatatom 314 207 5 0 0; +#X msg 129 30 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7; +#X msg 129 62 -7 -6 -5 -4 -3 test -1 0 1 2 3 4 5 6 7; +#X msg 132 103 test; +#X msg 252 175 set -5 test -4; +#X msg 312 103 bang; +#X msg 198 103 set 11 333; +#X obj 252 143 testmess 350; +#X msg 444 103 bang; +#X obj 384 143 testmess 200; +#X connect 0 0 1 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 8 0; +#X connect 9 0 7 0; +#X connect 10 0 7 0; +#X connect 11 0 7 0; +#X connect 12 0 0 0; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 15 0 0 0; +#X connect 16 0 18 0; +#X connect 17 0 0 0; +#X connect 18 0 0 0; +#X connect 19 0 20 0; +#X connect 20 0 0 0; diff --git a/test/cyclone/coll-print.pd b/test/cyclone/coll-print.pd new file mode 100644 index 0000000..8ef57dc --- /dev/null +++ b/test/cyclone/coll-print.pd @@ -0,0 +1,12 @@ +#N canvas 24 90 450 300 12; +#X obj 169 170 print; +#X obj 169 129 prepend dummy; +#X msg 169 83 set \$1; +#X obj 66 83 prepend :; +#X obj 66 40 inlet; +#X obj 169 40 inlet; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 3 0 1 0; +#X connect 4 0 3 0; +#X connect 5 0 2 0; diff --git a/test/cyclone/coll-test.pd b/test/cyclone/coll-test.pd new file mode 100644 index 0000000..d955ce1 --- /dev/null +++ b/test/cyclone/coll-test.pd @@ -0,0 +1,117 @@ +#N canvas 392 153 614 512 12; +#X obj 40 57 coll; +#C restore; +#X msg 40 20 debug; +#X obj 106 57 coll; +#C restore; +#X msg 106 20 debug; +#X msg 42 136 debug; +#X msg 184 136 debug; +#X obj 42 172 coll good.coll; +#C restore; +#X obj 184 205 coll good.coll; +#C restore; +#X msg 42 218 debug; +#X obj 42 280 coll good.coll; +#C restore; +#X msg 41 366 debug; +#X obj 41 406 coll bad.coll; +#C restore; +#X msg 113 218 dump; +#X msg 25 103 store one first element; +#X msg 260 103 store 2 2nd element; +#X obj 321 451 coll good.coll; +#C restore; +#X msg 265 136 store 3 3rd; +#X msg 248 172 store 4 4; +#X floatatom 113 248 5 0 0 0 - - -; +#X msg 205 248 renumber 11; +#X msg 246 280 swap 11 one; +#X msg 308 376 read good.coll; +#X msg 246 406 read; +#X msg 191 406 open; +#X obj 42 322 coll-print; +#X obj 41 444 coll-print; +#X msg 111 366 dump; +#X obj 167 57 coll missing; +#C restore; +#X msg 285 344 refer bad.coll; +#X msg 440 344 refer good.coll; +#X msg 443 415 write test.coll; +#X msg 379 415 write; +#X msg 349 172 flags 1 0; +#X msg 380 224 sort -1; +#X msg 394 248 sort -1 -1; +#X msg 409 280 sort 1; +#X msg 423 309 sort 1 -1; +#X msg 191 376 wclose; +#N canvas 502 158 450 423 large 0; +#X obj 241 341 coll big.coll; +#C restore; +#X msg 33 205 store \$1; +#X obj 33 277 testmess 10; +#X obj 33 92 Uzi; +#X msg 99 92 clear; +#X obj 33 57 t 0 b; +#X obj 33 169 t 0 b; +#X msg 167 277 wclose; +#X obj 241 380 print; +#X floatatom 164 341 5 0 0 0 - - -; +#X msg 261 277 sort -1 -1; +#X obj 129 205 random 10000; +#X msg 129 241 set 10 \$1; +#X msg 241 241 clear; +#X msg 33 21 5000; +#X obj 33 131 urn 50000; +#X msg 283 308 sort 1; +#X connect 0 0 8 0; +#X connect 1 0 2 0; +#X connect 2 0 0 0; +#X connect 3 0 15 0; +#X connect 4 0 15 0; +#X connect 5 0 3 0; +#X connect 5 1 4 0; +#X connect 6 0 1 0; +#X connect 6 1 11 0; +#X connect 7 0 0 0; +#X connect 9 0 0 0; +#X connect 10 0 0 0; +#X connect 11 0 12 0; +#X connect 12 0 2 0; +#X connect 13 0 0 0; +#X connect 14 0 5 0; +#X connect 15 0 6 0; +#X connect 16 0 0 0; +#X restore 320 20 pd large; +#X connect 1 0 0 0; +#X connect 3 0 2 0; +#X connect 4 0 6 0; +#X connect 5 0 7 0; +#X connect 8 0 9 0; +#X connect 9 0 24 0; +#X connect 9 1 24 1; +#X connect 10 0 11 0; +#X connect 11 0 25 0; +#X connect 11 1 25 1; +#X connect 12 0 9 0; +#X connect 13 0 6 0; +#X connect 14 0 7 0; +#X connect 16 0 7 0; +#X connect 17 0 7 0; +#X connect 18 0 9 0; +#X connect 19 0 15 0; +#X connect 20 0 15 0; +#X connect 21 0 15 0; +#X connect 22 0 15 0; +#X connect 23 0 15 0; +#X connect 26 0 11 0; +#X connect 28 0 15 0; +#X connect 29 0 15 0; +#X connect 30 0 15 0; +#X connect 31 0 15 0; +#X connect 32 0 7 0; +#X connect 33 0 15 0; +#X connect 34 0 15 0; +#X connect 35 0 15 0; +#X connect 36 0 15 0; +#X connect 37 0 15 0; diff --git a/test/cyclone/comb-test.pd b/test/cyclone/comb-test.pd new file mode 100644 index 0000000..dc2e599 --- /dev/null +++ b/test/cyclone/comb-test.pd @@ -0,0 +1,80 @@ +#N canvas 134 225 749 475 12; +#X floatatom 137 89 5 0 0; +#X floatatom 534 89 5 0 0; +#X msg 68 154 clear; +#X obj 36 427 dac~; +#X floatatom 376 89 5 0 0; +#X obj 220 119 osc~; +#X floatatom 220 89 5 0 0; +#X obj 137 154 line~; +#X msg 137 119 \$1 5; +#X obj 220 154 *~ 1; +#X floatatom 303 89 5 0 0; +#X floatatom 458 89 5 0 0; +#N canvas 80 0 592 295 graph1 0; +#X array test 1000 float 0; +#X coords 0 1 999 -1 200 140 1; +#X restore 522 282 graph; +#X obj 65 282 tabwrite~ test; +#X msg 65 246 bang; +#X obj 36 59 adc~; +#X obj 267 282 int; +#X msg 267 246 0; +#X msg 313 246 1; +#X obj 347 18 loadbang; +#X msg 220 59 0.33; +#X msg 137 59 2; +#X msg 303 59 1; +#X obj 534 154 line~; +#X msg 534 119 \$1 5; +#X obj 93 354 dbtorms; +#X obj 93 427 line~; +#X obj 36 390 *~; +#X msg 93 390 \$1 10; +#X obj 96 312 hsl 128 25 0 100 0 0 empty empty empty -2 -6 0 8 -24198 +-1 -1 0 0; +#X obj 267 312 vex_pool~ pool test.pool; +#X msg 458 59 0.4; +#X msg 376 59 0.7; +#X msg 534 59 0.66; +#X obj 36 209 comb~ 100 2 0.7 0.4 0.66; +#X connect 0 0 8 0; +#X connect 1 0 24 0; +#X connect 2 0 34 0; +#X connect 4 0 34 2; +#X connect 5 0 9 0; +#X connect 6 0 5 0; +#X connect 7 0 34 1; +#X connect 8 0 7 0; +#X connect 9 0 34 1; +#X connect 10 0 9 1; +#X connect 11 0 34 3; +#X connect 14 0 13 0; +#X connect 15 0 34 0; +#X connect 16 0 30 0; +#X connect 17 0 16 0; +#X connect 18 0 16 0; +#X connect 19 0 33 0; +#X connect 19 0 31 0; +#X connect 19 0 32 0; +#X connect 19 0 22 0; +#X connect 19 0 20 0; +#X connect 19 0 21 0; +#X connect 20 0 6 0; +#X connect 21 0 0 0; +#X connect 22 0 10 0; +#X connect 23 0 34 4; +#X connect 24 0 23 0; +#X connect 25 0 28 0; +#X connect 26 0 27 1; +#X connect 27 0 3 0; +#X connect 27 0 3 1; +#X connect 28 0 26 0; +#X connect 29 0 25 0; +#X connect 30 0 34 0; +#X connect 30 1 16 0; +#X connect 31 0 11 0; +#X connect 32 0 4 0; +#X connect 33 0 1 0; +#X connect 34 0 13 0; +#X connect 34 0 27 0; diff --git a/test/cyclone/comment-dotest.pd b/test/cyclone/comment-dotest.pd new file mode 100644 index 0000000..7a78080 --- /dev/null +++ b/test/cyclone/comment-dotest.pd @@ -0,0 +1,37 @@ +#N canvas 286 325 415 463 12; +#N canvas 454 204 548 368 doit 0; +#X obj 27 120 counter; +#X obj 27 254 pack 0 0 0; +#X obj 27 188 * 10; +#X obj 27 21 inlet; +#X obj 27 85 Uzi; +#X obj 27 53 t 0 b; +#X msg 73 85 set 0; +#X obj 27 220 + 10; +#X obj 81 220 + 10; +#X obj 138 220 + 7; +#X obj 27 154 t 0 0 0 0; +#X obj 81 188 *; +#X obj 138 188 * 3; +#X msg 27 289 \; pd-comment-dotest.pd obj \$1 \$2 comment 0 \$3 . test +; +#X connect 0 0 10 0; +#X connect 1 0 13 0; +#X connect 2 0 7 0; +#X connect 3 0 5 0; +#X connect 4 0 0 0; +#X connect 5 0 4 0; +#X connect 5 1 6 0; +#X connect 6 0 0 0; +#X connect 7 0 1 0; +#X connect 8 0 1 1; +#X connect 9 0 1 2; +#X connect 10 0 2 0; +#X connect 10 1 11 0; +#X connect 10 2 11 1; +#X connect 10 3 12 0; +#X connect 11 0 8 0; +#X connect 12 0 9 0; +#X restore 283 92 pd doit; +#X msg 283 60 20; +#X connect 1 0 0 0; diff --git a/test/cyclone/comment-ogonki.pd b/test/cyclone/comment-ogonki.pd new file mode 100644 index 0000000..1e0902e --- /dev/null +++ b/test/cyclone/comment-ogonki.pd @@ -0,0 +1,9 @@ +#N canvas 232 153 767 466 12; +#X obj 41 14 comment 550 72 helvetica iso8859-2 0 255 0 0 ê󱶳¿¼æñ +ÊÓ¡¦£¯¬ÆÑ; +#X obj 48 321 comment 200 24 courier iso8859-2 0 0 255 0 ê󱶳¿¼æñ +ÊÓ¡¦£¯¬ÆÑ; +#X obj 275 316 comment 200 24 times iso8859-2 0 0 255 255 ê󱶳¿¼æñ +ÊÓ¡¦£¯¬ÆÑ; +#X obj 500 316 comment 200 24 helvetica iso8859-2 0 255 255 0 ê󱶳¿¼æñ +ÊÓ¡¦£¯¬ÆÑ; diff --git a/test/cyclone/comment-test.pd b/test/cyclone/comment-test.pd new file mode 100644 index 0000000..03edff6 --- /dev/null +++ b/test/cyclone/comment-test.pd @@ -0,0 +1,21 @@ +#N canvas 85 23 415 463 12; +#X obj 10 10 comment 0 7 courier ? 0 0 0 0 test; +#X obj 20 10 comment 0 10 courier ? 0 0 0 0 test; +#X obj 30 14 comment 0 13 courier ? 0 0 0 0 test; +#X obj 40 19 comment 0 16 courier ? 0 0 0 0 test; +#X obj 50 26 comment 0 19 courier ? 0 0 0 0 test; +#X obj 60 35 comment 0 22 courier ? 0 0 0 0 test; +#X obj 70 46 comment 0 25 courier ? 0 0 0 0 test; +#X obj 80 59 comment 0 28 courier ? 0 0 0 0 test; +#X obj 90 74 comment 0 31 courier ? 0 0 0 0 test; +#X obj 100 91 comment 0 34 courier ? 0 0 0 0 test; +#X obj 110 110 comment 0 37 courier ? 0 0 0 0 test; +#X obj 120 131 comment 0 40 courier ? 0 0 0 0 test; +#X obj 130 154 comment 0 43 courier ? 0 0 0 0 test; +#X obj 140 179 comment 0 46 courier ? 0 0 0 0 test; +#X obj 150 206 comment 0 49 courier ? 0 0 0 0 test; +#X obj 160 235 comment 0 52 courier ? 0 0 0 0 test; +#X obj 170 266 comment 0 55 courier ? 0 0 0 0 test; +#X obj 180 299 comment 0 58 courier ? 0 0 0 0 test; +#X obj 190 334 comment 0 61 courier ? 0 0 0 0 test; +#X obj 200 371 comment 0 64 courier ? 0 0 0 0 test; diff --git a/test/cyclone/count-test.pd b/test/cyclone/count-test.pd new file mode 100644 index 0000000..27fe454 --- /dev/null +++ b/test/cyclone/count-test.pd @@ -0,0 +1,19 @@ +#N canvas 229 256 450 300 12; +#X obj 121 167 snapshot~; +#X obj 294 122 metro 30; +#X obj 294 88 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X floatatom 121 215 0 0 0; +#X msg 121 60 bang; +#X msg 59 60 stop; +#X obj 121 118 count~; +#X msg 177 60 3; +#X msg 232 60 100; +#X connect 0 0 3 0; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 4 0 6 0; +#X connect 5 0 6 0; +#X connect 6 0 0 0; +#X connect 7 0 6 0; +#X connect 8 0 6 1; diff --git a/test/cyclone/counter-test.pd b/test/cyclone/counter-test.pd new file mode 100644 index 0000000..5716b52 --- /dev/null +++ b/test/cyclone/counter-test.pd @@ -0,0 +1,46 @@ +#N canvas 476 253 450 390 12; +#X obj 68 234 counter; +#X floatatom 68 344 0 0 0; +#X msg 16 173 bang; +#X msg 68 35 up; +#X msg 80 61 down; +#X msg 89 87 updown; +#X msg 96 117 bang; +#X msg 106 145 bang; +#X msg 116 173 bang; +#X msg 126 203 bang; +#X floatatom 152 117 5 0 0; +#X floatatom 161 145 5 0 0; +#X floatatom 167 173 5 0 0; +#X floatatom 177 203 5 0 0; +#X floatatom 126 259 5 0 0; +#X obj 87 315 print second; +#X obj 106 286 print third; +#X msg 319 203 max \$1; +#X msg 243 203 min \$1; +#X floatatom 243 177 5 0 0; +#X floatatom 319 177 5 0 0; +#X msg 16 117 inc; +#X msg 16 145 dec; +#X connect 0 0 1 0; +#X connect 0 1 15 0; +#X connect 0 2 16 0; +#X connect 0 3 14 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 1; +#X connect 7 0 0 2; +#X connect 8 0 0 3; +#X connect 9 0 0 4; +#X connect 10 0 0 1; +#X connect 11 0 0 2; +#X connect 12 0 0 3; +#X connect 13 0 0 4; +#X connect 17 0 0 0; +#X connect 18 0 0 0; +#X connect 19 0 18 0; +#X connect 20 0 17 0; +#X connect 21 0 0 0; +#X connect 22 0 0 0; diff --git a/test/cyclone/cycle-test.pd b/test/cyclone/cycle-test.pd new file mode 100644 index 0000000..97d008e --- /dev/null +++ b/test/cyclone/cycle-test.pd @@ -0,0 +1,30 @@ +#N canvas 257 195 450 300 12; +#X msg 77 196 bang; +#X obj 131 235 print a; +#X obj 218 235 print b; +#X msg 131 153 test; +#X msg 192 152 symbol test; +#X msg 72 86 1 2 3 \, 4 5; +#X msg 204 86 1 2 3; +#X msg 230 115 4 5; +#X obj 131 195 cycle 2 1; +#X msg 242 18 bang; +#X obj 204 59 del 100; +#X obj 293 59 del 100; +#X obj 312 205 cycle; +#X obj 312 237 print; +#X msg 312 151 test 1 2 3; +#X connect 0 0 8 0; +#X connect 3 0 8 0; +#X connect 4 0 8 0; +#X connect 5 0 8 0; +#X connect 6 0 8 0; +#X connect 7 0 8 0; +#X connect 8 0 1 0; +#X connect 8 1 2 0; +#X connect 9 0 10 0; +#X connect 9 0 11 0; +#X connect 10 0 6 0; +#X connect 11 0 7 0; +#X connect 12 0 13 0; +#X connect 14 0 12 0; diff --git a/test/cyclone/cyclone-test.pd b/test/cyclone/cyclone-test.pd new file mode 100644 index 0000000..d2919c0 --- /dev/null +++ b/test/cyclone/cyclone-test.pd @@ -0,0 +1,54 @@ +#N canvas 430 63 531 442 12; +#X obj 39 399 cyclone; +#X msg 39 19 bang; +#X msg 244 19 import; +#X obj 42 212 forward texthelp; +#X obj 63 278 r texthelp; +#X msg 56 245 send binhelp; +#X msg 182 245 send texthelp; +#X obj 90 309 r binhelp; +#X msg 148 112 pv; +#X msg 64 112 coll; +#X msg 207 83 triangle~; +#X msg 148 83 comb~; +#X msg 64 83 allpass~; +#X msg 207 112 message; +#X msg 207 141 line~; +#X obj 90 338 sprintf import ../../../ref/c74help/bin/%s.help; +#X obj 63 369 sprintf import ../../../ref/c74help/text/%s.help; +#X msg 92 19 dummies; +#X obj 39 48 cyclone; +#X msg 274 141 groove~; +#X msg 207 170 scope~; +#X msg 306 83 trapezoid~; +#X msg 306 112 kink~; +#X msg 290 170 rate~; +#X msg 360 170 pong~; +#X msg 360 141 vectral~; +#X msg 170 19 reps; +#X msg 378 112 bitand~; +#X connect 1 0 18 0; +#X connect 2 0 18 0; +#X connect 4 0 16 0; +#X connect 5 0 3 0; +#X connect 6 0 3 0; +#X connect 7 0 15 0; +#X connect 8 0 3 0; +#X connect 9 0 3 0; +#X connect 10 0 3 0; +#X connect 11 0 3 0; +#X connect 12 0 3 0; +#X connect 13 0 3 0; +#X connect 14 0 3 0; +#X connect 15 0 0 0; +#X connect 16 0 0 0; +#X connect 17 0 18 0; +#X connect 19 0 3 0; +#X connect 20 0 3 0; +#X connect 21 0 3 0; +#X connect 22 0 3 0; +#X connect 23 0 3 0; +#X connect 24 0 3 0; +#X connect 25 0 3 0; +#X connect 26 0 18 0; +#X connect 27 0 3 0; diff --git a/test/cyclone/decide-test.pd b/test/cyclone/decide-test.pd new file mode 100644 index 0000000..27c534c --- /dev/null +++ b/test/cyclone/decide-test.pd @@ -0,0 +1,27 @@ +#N canvas 242 258 450 300 12; +#X obj 116 111 decide; +#X msg 47 68 bang; +#X obj 116 68 Uzi; +#X obj 116 198 counter; +#X obj 200 198 counter; +#X obj 116 151 sel 0 1; +#X floatatom 116 249 0 0 0; +#X floatatom 200 249 0 0 0; +#X msg 116 29 10000; +#X obj 276 73 decide; +#X msg 237 29 bang; +#X msg 325 29 1; +#X msg 382 29 -1; +#X obj 276 111 print; +#X connect 0 0 5 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 6 0; +#X connect 4 0 7 0; +#X connect 5 0 3 0; +#X connect 5 1 4 0; +#X connect 8 0 2 0; +#X connect 9 0 13 0; +#X connect 10 0 9 0; +#X connect 11 0 9 1; +#X connect 12 0 9 1; diff --git a/test/cyclone/drunk-test.pd b/test/cyclone/drunk-test.pd new file mode 100644 index 0000000..fdd6087 --- /dev/null +++ b/test/cyclone/drunk-test.pd @@ -0,0 +1,45 @@ +#N canvas 366 150 514 397 12; +#X obj 43 265 drunk; +#X obj 43 305 print; +#X msg 43 112 bang; +#X msg 53 142 seed 123; +#X floatatom 147 172 5 0 0; +#X floatatom 171 196 5 0 0; +#X floatatom 189 219 5 0 0; +#X msg 147 142 11 22 33; +#X obj 282 305 print; +#X msg 282 112 bang; +#X msg 292 142 seed 123; +#X floatatom 386 172 5 0 0; +#X floatatom 410 196 5 0 0; +#X floatatom 428 219 5 0 0; +#X msg 386 142 11 22 33; +#X obj 282 265 drunk 100 -2; +#X msg 124 265 -----; +#X msg 62 177 set 50; +#X msg 301 177 set 50; +#X msg 43 28 1000; +#X obj 43 66 Uzi; +#X msg 282 28 1000; +#X obj 282 66 Uzi; +#X connect 0 0 1 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 1; +#X connect 6 0 0 2; +#X connect 7 0 0 0; +#X connect 9 0 15 0; +#X connect 10 0 15 0; +#X connect 11 0 15 0; +#X connect 12 0 15 1; +#X connect 13 0 15 2; +#X connect 14 0 15 0; +#X connect 15 0 8 0; +#X connect 16 0 1 0; +#X connect 17 0 0 0; +#X connect 18 0 15 0; +#X connect 19 0 20 0; +#X connect 20 0 0 0; +#X connect 21 0 22 0; +#X connect 22 0 15 0; diff --git a/test/cyclone/forward-test.pd b/test/cyclone/forward-test.pd new file mode 100644 index 0000000..af4b299 --- /dev/null +++ b/test/cyclone/forward-test.pd @@ -0,0 +1,27 @@ +#N canvas 489 306 462 351 12; +#X msg 197 169 send there; +#X msg 197 205 send elsewhere; +#X msg 197 240 send; +#X obj 62 45 r there; +#X obj 167 45 r elsewhere; +#X obj 62 83 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 167 83 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 67 195 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 207 83 print; +#X msg 100 124 any message; +#X obj 100 279 forward here; +#X obj 266 240 r here; +#X obj 266 279 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X connect 0 0 10 0; +#X connect 1 0 10 0; +#X connect 2 0 10 0; +#X connect 3 0 5 0; +#X connect 4 0 6 0; +#X connect 4 0 8 0; +#X connect 7 0 10 0; +#X connect 9 0 10 0; +#X connect 11 0 12 0; diff --git a/test/cyclone/frameaccum-test.pd b/test/cyclone/frameaccum-test.pd new file mode 100644 index 0000000..61e4ffd --- /dev/null +++ b/test/cyclone/frameaccum-test.pd @@ -0,0 +1,15 @@ +#N canvas 0 0 450 300 12; +#X obj 31 52 frameaccum~; +#X obj 31 93 capture~; +#X obj 177 183 Scope~ 234 106 8 3 256 0 1 0 0 0 0 102 255 51 135 135 +135 0; +#X obj 325 93 capture~; +#X obj 325 52 framedelta~; +#X msg 33 143 range 0 1 \, bufsize 256 \, 8; +#X obj 177 13 train~ 46.4399; +#X connect 0 0 1 0; +#X connect 4 0 3 0; +#X connect 5 0 2 0; +#X connect 6 0 2 0; +#X connect 6 0 0 0; +#X connect 6 0 4 0; diff --git a/test/cyclone/fromsymbol-test.pd b/test/cyclone/fromsymbol-test.pd new file mode 100644 index 0000000..cacbc83 --- /dev/null +++ b/test/cyclone/fromsymbol-test.pd @@ -0,0 +1,64 @@ +#N canvas 352 169 704 560 12; +#X obj 81 108 tosymbol; +#X msg 81 62 one two three; +#X obj 81 147 fromsymbol; +#X msg 29 62 one; +#X obj 243 62 testmess 100; +#X msg 243 31 test; +#X msg 385 31 test; +#X obj 385 62 testmess 300; +#X obj 81 190 route one test; +#X obj 81 229 print one; +#X obj 184 229 print test; +#X obj 293 229 print unknown; +#X obj 42 316 tosymbol; +#X obj 42 359 fromsymbol; +#X floatatom 106 416 5 0 0; +#X floatatom 158 390 5 0 0; +#X floatatom 42 282 5 0 0; +#X obj 158 359 f; +#X obj 268 322 tosymbol; +#X obj 268 359 fromsymbol; +#X msg 133 316 99; +#X msg 178 316 0.99; +#X msg 133 282 1 2 3; +#X obj 42 416 print; +#X msg 268 397 test2; +#X msg 364 282 set test2; +#X msg 268 282 set test1; +#X msg 476 246 1 2 3 4; +#X obj 476 282 tosymbol; +#X obj 476 322 fromsymbol; +#X obj 476 359 unpack 0 0 0 0; +#X obj 476 397 print; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 2 0 8 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 4 0; +#X connect 6 0 7 0; +#X connect 7 0 0 0; +#X connect 8 0 9 0; +#X connect 8 1 10 0; +#X connect 8 2 11 0; +#X connect 12 0 13 0; +#X connect 12 0 17 0; +#X connect 13 0 14 0; +#X connect 13 0 23 0; +#X connect 16 0 12 0; +#X connect 17 0 15 0; +#X connect 18 0 19 0; +#X connect 19 0 24 0; +#X connect 20 0 13 0; +#X connect 21 0 13 0; +#X connect 22 0 13 0; +#X connect 25 0 18 0; +#X connect 26 0 18 0; +#X connect 27 0 28 0; +#X connect 28 0 29 0; +#X connect 29 0 30 0; +#X connect 30 0 31 0; +#X connect 30 1 31 0; +#X connect 30 2 31 0; +#X connect 30 3 31 0; diff --git a/test/cyclone/funbuff-etest.pd b/test/cyclone/funbuff-etest.pd new file mode 100644 index 0000000..5d6a1a3 --- /dev/null +++ b/test/cyclone/funbuff-etest.pd @@ -0,0 +1,164 @@ +#N canvas 116 34 735 514 12; +#X msg 49 113 clear; +#X floatatom 172 181 5 0 0; +#X obj 212 243 * -1; +#X obj 172 213 t 0 0; +#X floatatom 172 147 5 0 0; +#X obj 279 113 Uzi; +#X msg 49 181 debug \$1; +#X msg 71 147 1; +#X obj 279 71 t 0 0; +#X msg 224 34 1000; +#X msg 279 34 10000; +#X msg 173 34 100; +#X obj 530 147 counter; +#X obj 530 113 Uzi; +#X msg 595 34 100000; +#X msg 475 34 1000; +#X msg 530 34 10000; +#X msg 424 34 100; +#X msg 578 113 set 0; +#X obj 530 71 t 0 b; +#X msg 114 147 2; +#X obj 279 147 urn; +#X msg 344 34 100000; +#X obj 531 306 counter; +#X obj 531 271 Uzi; +#X msg 579 271 set 0; +#X obj 531 235 t 0 b; +#X msg 531 196 50; +#X msg 582 196 100; +#X obj 429 235 Uzi; +#X msg 429 196 50; +#X msg 480 196 100; +#X obj 429 271 urn 100; +#X obj 49 355 funbuff; +#C embed 1; +#C set 1 -1 2 -2 3 -3 5 -5 6 -6 7 -7 8 -8 9 -9 10 -10 11 -11 12 -12 +13 -13 14 -14 15 -15 16 -16 18 -18 19 -19 20 -20 21 -21 22 -22 23 -23 +25 -25 26 -26 27 -27 28 -28 30 -30 31 -31 33 -33 34 -34; +#C restore; +#X obj 49 426 print; +#X msg 60 213 bang; +#X msg 69 243 dump; +#X obj 49 389 pack; +#X msg 126 288 set; +#X msg 194 288 set 1 2 3; +#X msg 171 83 goto 15; +#X msg 171 112 next; +#X msg 148 426 write test.funbuff; +#X msg 157 461 read test.funbuff; +#X msg 184 364 read; +#X msg 184 393 write; +#X obj 398 389 funbuff test.funbuff; +#C embed 1; +#C set 0 -0 1 -1 2 -2 3 -3 4 -4 5 -5 6 -6 7 -7 8 -8 9 -9 10 -10 11 +-11 12 -12 13 -13 14 -14 15 -15 16 -16 17 -17 18 -18 19 -19 20 -20 +21 -21 22 -22 23 -23 24 -24 25 -25 26 -26 27 -27 28 -28 29 -29 30 -30 +31 -31 32 -32 33 -33 34 -34 35 -35 36 -36 37 -37 38 -38 39 -39 40 -40 +41 -41 42 -42 43 -43 44 -44 45 -45 46 -46 47 -47 48 -48 49 -49 50 -50 +51 -51 52 -52 53 -53 54 -54 55 -55 56 -56 57 -57 58 -58 59 -59 60 -60 +61 -61 62 -62 63 -63 64 -64 65 -65 66 -66 67 -67 68 -68 69 -69 70 -70 +71 -71 72 -72 73 -73 74 -74 75 -75 76 -76 77 -77 78 -78 79 -79 80 -80 +81 -81 82 -82 83 -83 84 -84 85 -85 86 -86 87 -87 88 -88 89 -89 90 -90 +91 -91 92 -92 93 -93 94 -94 95 -95 96 -96 97 -97 98 -98 99 -99; +#C restore; +#X obj 398 461 print; +#X obj 398 426 pack; +#X msg 398 355 bang; +#X msg 456 355 next; +#X msg 514 355 goto 0; +#N canvas 478 69 552 396 interp 0; +#X obj 52 124 funbuff test.funbuff; +#C restore; +#X msg 52 85 interp \$1; +#X floatatom 52 53 5 0 0; +#N canvas 0 0 450 300 graph1 0; +#X array t 100 float 1; +#A 0 0 -0.0285716 -0.0548876 -0.0812036 -0.10752 -0.133836 -0.160152 +-0.186468 -0.212784 -0.2391 -0.265416 -0.291732 -0.318048 -0.344364 +-0.37068 -0.396996 -0.423312 -0.449628 -0.475944 -0.50226 -0.528575 +-0.55429 -0.580004 -0.605719 -0.631433 -0.657148 -0.682863 -0.708577 +-0.734292 -0.760006 -0.785721 -0.811435 -0.83715 -0.862864 -0.888579 +-0.914293 -0.939293 -0.964293 -0.989294 -1.01429 -1.04287 -1.07144 +-1.10001 -1.12382 -1.14763 -1.17144 -1.18572 -1.20001 -1.22858 -1.25715 +-1.28096 -1.30477 -1.32858 -1.35715 -1.40715 -1.45715 -1.40001 -1.38573 +-1.15715 -0.942865 -0.0285715 0.242859 0.343812 0.444765 0.545719 0.646672 +0.747625 0.848578 0.949531 1.05048 1.15144 1.25239 1.35334 1.4543 1.55525 +1.6562 1.77144 1.84922 1.927 2.68574 2.67145 2.65716 2.64288 2.62859 +2.61431 2.6041 2.5939 2.58369 2.57349 2.56329 2.55308 2.54288 2.54288 +2.54696 2.55104 2.55512 2.5592 2.56329 2.56737 2.62859; +#X coords 0 1 99 -1 200 140 1; +#X restore 290 173 graph; +#X floatatom 184 53 5 0 0; +#X msg 184 85 interptab \$1 t; +#X floatatom 52 168 0 0 0; +#X connect 0 0 6 0; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 4 0 5 0; +#X connect 5 0 0 0; +#X restore 49 34 pd interp; +#X msg 306 235 embed 1; +#X msg 332 355 dump; +#X connect 0 0 33 0; +#X connect 1 0 3 0; +#X connect 2 0 33 1; +#X connect 3 0 33 0; +#X connect 3 1 2 0; +#X connect 4 0 33 0; +#X connect 5 0 21 0; +#X connect 6 0 33 0; +#X connect 7 0 6 0; +#X connect 8 0 5 0; +#X connect 8 1 21 1; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 11 0 8 0; +#X connect 12 0 3 0; +#X connect 13 0 12 0; +#X connect 14 0 19 0; +#X connect 15 0 19 0; +#X connect 16 0 19 0; +#X connect 17 0 19 0; +#X connect 18 0 12 0; +#X connect 19 0 13 0; +#X connect 19 1 18 0; +#X connect 20 0 6 0; +#X connect 21 0 3 0; +#X connect 22 0 8 0; +#X connect 23 0 33 0; +#X connect 24 0 23 0; +#X connect 25 0 23 0; +#X connect 26 0 24 0; +#X connect 26 1 25 0; +#X connect 27 0 26 0; +#X connect 28 0 26 0; +#X connect 29 0 32 0; +#X connect 30 0 29 0; +#X connect 31 0 29 0; +#X connect 32 0 33 0; +#X connect 33 0 37 0; +#X connect 33 1 37 1; +#X connect 33 2 34 0; +#X connect 35 0 33 0; +#X connect 36 0 33 0; +#X connect 37 0 34 0; +#X connect 38 0 33 0; +#X connect 39 0 33 0; +#X connect 40 0 33 0; +#X connect 41 0 33 0; +#X connect 42 0 33 0; +#X connect 43 0 33 0; +#X connect 44 0 33 0; +#X connect 45 0 33 0; +#X connect 46 0 48 0; +#X connect 46 1 48 1; +#X connect 46 2 47 0; +#X connect 48 0 47 0; +#X connect 49 0 46 0; +#X connect 50 0 46 0; +#X connect 51 0 46 0; +#X connect 53 0 46 0; +#X connect 53 0 33 0; +#X connect 54 0 46 0; diff --git a/test/cyclone/funbuff-test.pd b/test/cyclone/funbuff-test.pd new file mode 100644 index 0000000..230368e --- /dev/null +++ b/test/cyclone/funbuff-test.pd @@ -0,0 +1,149 @@ +#N canvas 116 34 735 514 12; +#X msg 49 113 clear; +#X floatatom 172 181 5 0 0; +#X obj 212 243 * -1; +#X obj 172 213 t 0 0; +#X floatatom 172 147 5 0 0; +#X obj 279 113 Uzi; +#X msg 49 181 debug \$1; +#X msg 71 147 1; +#X obj 279 71 t 0 0; +#X msg 224 34 1000; +#X msg 279 34 10000; +#X msg 173 34 100; +#X obj 530 147 counter; +#X obj 530 113 Uzi; +#X msg 595 34 100000; +#X msg 475 34 1000; +#X msg 530 34 10000; +#X msg 424 34 100; +#X msg 578 113 set 0; +#X obj 530 71 t 0 b; +#X msg 114 147 2; +#X obj 279 147 urn; +#X msg 344 34 100000; +#X obj 531 306 counter; +#X obj 531 271 Uzi; +#X msg 579 271 set 0; +#X obj 531 235 t 0 b; +#X msg 531 196 50; +#X msg 582 196 100; +#X obj 429 235 Uzi; +#X msg 429 196 50; +#X msg 480 196 100; +#X obj 429 271 urn 100; +#X obj 49 355 funbuff; +#C restore; +#X obj 49 426 print; +#X msg 60 213 bang; +#X msg 69 243 dump; +#X obj 49 389 pack; +#X msg 126 288 set; +#X msg 194 288 set 1 2 3; +#X msg 171 83 goto 15; +#X msg 171 112 next; +#X msg 148 426 write test.funbuff; +#X msg 157 461 read test.funbuff; +#X msg 184 364 read; +#X msg 184 393 write; +#X obj 398 389 funbuff test.funbuff; +#C restore; +#X obj 398 461 print; +#X obj 398 426 pack; +#X msg 398 355 bang; +#X msg 456 355 next; +#X msg 514 355 goto 0; +#N canvas 478 69 552 396 interp 0; +#X obj 52 124 funbuff test.funbuff; +#C restore; +#X msg 52 85 interp \$1; +#X floatatom 52 53 5 0 0; +#N canvas 0 0 450 300 graph1 0; +#X array t 100 float 1; +#A 0 0 -0.0285716 -0.0548876 -0.0812036 -0.10752 -0.133836 -0.160152 +-0.186468 -0.212784 -0.2391 -0.265416 -0.291732 -0.318048 -0.344364 +-0.37068 -0.396996 -0.423312 -0.449628 -0.475944 -0.50226 -0.528575 +-0.55429 -0.580004 -0.605719 -0.631433 -0.657148 -0.682863 -0.708577 +-0.734292 -0.760006 -0.785721 -0.811435 -0.83715 -0.862864 -0.888579 +-0.914293 -0.939293 -0.964293 -0.989294 -1.01429 -1.04287 -1.07144 +-1.10001 -1.12382 -1.14763 -1.17144 -1.18572 -1.20001 -1.22858 -1.25715 +-1.28096 -1.30477 -1.32858 -1.35715 -1.40715 -1.45715 -1.40001 -1.38573 +-1.15715 -0.942865 -0.0285715 0.242859 0.343812 0.444765 0.545719 0.646672 +0.747625 0.848578 0.949531 1.05048 1.15144 1.25239 1.35334 1.4543 1.55525 +1.6562 1.77144 1.84922 1.927 2.68574 2.67145 2.65716 2.64288 2.62859 +2.61431 2.6041 2.5939 2.58369 2.57349 2.56329 2.55308 2.54288 2.54288 +2.54696 2.55104 2.55512 2.5592 2.56329 2.56737 2.62859; +#X coords 0 1 99 -1 200 140 1; +#X restore 290 173 graph; +#X floatatom 184 53 5 0 0; +#X msg 184 85 interptab \$1 t; +#X floatatom 52 168 0 0 0; +#X connect 0 0 6 0; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 4 0 5 0; +#X connect 5 0 0 0; +#X restore 49 34 pd interp; +#X msg 306 235 embed 1; +#X msg 332 355 dump; +#X connect 0 0 33 0; +#X connect 1 0 3 0; +#X connect 2 0 33 1; +#X connect 3 0 33 0; +#X connect 3 1 2 0; +#X connect 4 0 33 0; +#X connect 5 0 21 0; +#X connect 6 0 33 0; +#X connect 7 0 6 0; +#X connect 8 0 5 0; +#X connect 8 1 21 1; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 11 0 8 0; +#X connect 12 0 3 0; +#X connect 13 0 12 0; +#X connect 14 0 19 0; +#X connect 15 0 19 0; +#X connect 16 0 19 0; +#X connect 17 0 19 0; +#X connect 18 0 12 0; +#X connect 19 0 13 0; +#X connect 19 1 18 0; +#X connect 20 0 6 0; +#X connect 21 0 3 0; +#X connect 22 0 8 0; +#X connect 23 0 33 0; +#X connect 24 0 23 0; +#X connect 25 0 23 0; +#X connect 26 0 24 0; +#X connect 26 1 25 0; +#X connect 27 0 26 0; +#X connect 28 0 26 0; +#X connect 29 0 32 0; +#X connect 30 0 29 0; +#X connect 31 0 29 0; +#X connect 32 0 33 0; +#X connect 33 0 37 0; +#X connect 33 1 37 1; +#X connect 33 2 34 0; +#X connect 35 0 33 0; +#X connect 36 0 33 0; +#X connect 37 0 34 0; +#X connect 38 0 33 0; +#X connect 39 0 33 0; +#X connect 40 0 33 0; +#X connect 41 0 33 0; +#X connect 42 0 33 0; +#X connect 43 0 33 0; +#X connect 44 0 33 0; +#X connect 45 0 33 0; +#X connect 46 0 48 0; +#X connect 46 1 48 1; +#X connect 46 2 47 0; +#X connect 48 0 47 0; +#X connect 49 0 46 0; +#X connect 50 0 46 0; +#X connect 51 0 46 0; +#X connect 53 0 46 0; +#X connect 53 0 33 0; +#X connect 54 0 46 0; diff --git a/test/cyclone/funnel-test.pd b/test/cyclone/funnel-test.pd new file mode 100644 index 0000000..3580e5d --- /dev/null +++ b/test/cyclone/funnel-test.pd @@ -0,0 +1,33 @@ +#N canvas 557 414 450 300 12; +#X obj 93 108 funnel 5; +#X obj 93 147 spray 5; +#X obj 58 200 print a; +#X obj 174 200 print e; +#X msg 116 64 bang; +#X msg 49 64 2 3 4; +#X msg 172 64 5 6 7; +#X msg 172 26 -7; +#X msg 49 26 -4; +#X obj 245 64 testmess 50; +#X msg 245 26 11 test; +#X obj 187 147 print; +#X obj 283 147 funnel 1 7; +#X msg 283 108 99; +#X msg 331 108 list test; +#X msg 222 108 bang; +#X connect 0 0 1 0; +#X connect 0 0 11 0; +#X connect 1 0 2 0; +#X connect 1 4 3 0; +#X connect 4 0 0 0; +#X connect 4 0 0 4; +#X connect 5 0 0 0; +#X connect 6 0 0 4; +#X connect 7 0 0 4; +#X connect 8 0 0 0; +#X connect 9 0 0 4; +#X connect 10 0 9 0; +#X connect 12 0 11 0; +#X connect 13 0 12 0; +#X connect 14 0 12 0; +#X connect 15 0 12 0; diff --git a/test/cyclone/gate-test.pd b/test/cyclone/gate-test.pd new file mode 100644 index 0000000..80cdb61 --- /dev/null +++ b/test/cyclone/gate-test.pd @@ -0,0 +1,48 @@ +#N canvas 250 108 629 425 12; +#X obj 209 222 switch 11 0 padding; +#X msg 90 37 bang; +#X msg 141 37 2; +#X msg 184 37 symbol three; +#X msg 264 67 1 2 3 4; +#X msg 318 94 five is anything; +#X msg 34 37 bang; +#X obj 34 67 grab; +#X floatatom 34 182 5 0 0; +#X floatatom 54 113 5 0 0; +#X obj 209 274 route bang float symbol list; +#X obj 209 314 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 270 310 5 0 0; +#X symbolatom 332 310 10 0 0; +#X obj 394 347 print list; +#X obj 456 310 print anything; +#X msg 357 123 last is anything too; +#X obj 227 165 gate 11 0 padding; +#X connect 0 0 10 0; +#X connect 1 0 17 1; +#X connect 2 0 17 1; +#X connect 3 0 17 1; +#X connect 4 0 17 1; +#X connect 5 0 17 1; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 7 1 17 0; +#X connect 9 0 0 0; +#X connect 9 0 17 0; +#X connect 10 0 11 0; +#X connect 10 1 12 0; +#X connect 10 2 13 0; +#X connect 10 3 14 0; +#X connect 10 4 15 0; +#X connect 16 0 17 1; +#X connect 17 0 0 1; +#X connect 17 1 0 2; +#X connect 17 2 0 3; +#X connect 17 3 0 4; +#X connect 17 4 0 5; +#X connect 17 5 0 6; +#X connect 17 6 0 7; +#X connect 17 7 0 8; +#X connect 17 8 0 9; +#X connect 17 9 0 10; +#X connect 17 10 0 11; diff --git a/test/cyclone/good.coll b/test/cyclone/good.coll new file mode 100644 index 0000000..fcbd428 --- /dev/null +++ b/test/cyclone/good.coll @@ -0,0 +1,4 @@ +11, testing coll; +12, who is going to do that?; +13 !, not; +me 14, and you?; diff --git a/test/cyclone/grab-test.pd b/test/cyclone/grab-test.pd new file mode 100644 index 0000000..7d1b31b --- /dev/null +++ b/test/cyclone/grab-test.pd @@ -0,0 +1,42 @@ +#N canvas 402 375 591 368 12; +#X obj 252 43 r t1; +#X msg 121 43 set t2; +#X obj 495 129 r t2; +#X obj 27 175 print 1st; +#X obj 103 129 print 2nd; +#X obj 252 253 print pass1; +#X obj 292 214 print pass2; +#X obj 27 89 grab 2 t1; +#X obj 419 43 r t1; +#X obj 419 253 print pass3; +#X floatatom 27 43 5 0 0; +#X floatatom 286 129 5 0 0; +#X obj 252 175 t 0 b; +#X obj 419 175 + 100; +#X obj 495 175 print t2; +#X obj 271 83 print t1-a; +#X obj 445 83 print t1-b; +#X obj 142 214 grab; +#X obj 204 294 +; +#X floatatom 142 293 5 0 0; +#X msg 142 175 \$1 1; +#X obj 173 255 grab; +#X connect 0 0 12 0; +#X connect 0 0 15 0; +#X connect 1 0 7 0; +#X connect 2 0 12 0; +#X connect 2 0 14 0; +#X connect 7 0 3 0; +#X connect 7 1 4 0; +#X connect 8 0 13 0; +#X connect 8 0 16 0; +#X connect 10 0 7 0; +#X connect 10 0 20 0; +#X connect 11 0 12 0; +#X connect 12 0 5 0; +#X connect 12 1 6 0; +#X connect 13 0 9 0; +#X connect 17 0 19 0; +#X connect 17 1 21 0; +#X connect 20 0 17 0; +#X connect 21 1 18 0; diff --git a/test/cyclone/index-test.pd b/test/cyclone/index-test.pd new file mode 100644 index 0000000..ea925fd --- /dev/null +++ b/test/cyclone/index-test.pd @@ -0,0 +1,51 @@ +#N canvas 391 378 743 455 12; +#N canvas 0 0 450 300 graph1 0; +#X array 0-t 100 float 0; +#X coords 0 1 99 -1 200 140 1; +#X restore 279 34 graph; +#X obj 43 280 index~ t; +#X obj 43 321 snapshot~; +#X floatatom 43 359 5 0 0; +#X floatatom 43 245 5 0 0; +#X obj 155 280 metro 10; +#X obj 155 245 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#N canvas 0 0 450 300 graph1 0; +#X array t 100 float 0; +#X coords 0 1 99 -1 200 140 1; +#X restore 37 34 graph; +#X obj 273 321 snapshot~; +#X floatatom 273 359 5 0 0; +#X floatatom 273 245 5 0 0; +#X obj 385 280 metro 10; +#X obj 385 245 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 273 280 index~ t 1; +#N canvas 0 0 450 300 graph1 0; +#X array 1-t 100 float 0; +#X coords 0 1 99 -1 200 140 1; +#X restore 518 34 graph; +#X msg 121 202 1; +#X msg 161 202 2; +#X msg 80 202 0; +#X msg 324 202 1; +#X msg 364 202 2; +#X msg 283 202 0; +#X msg 408 202 3; +#X connect 1 0 2 0; +#X connect 2 0 3 0; +#X connect 4 0 1 0; +#X connect 5 0 2 0; +#X connect 6 0 5 0; +#X connect 8 0 9 0; +#X connect 10 0 13 0; +#X connect 11 0 8 0; +#X connect 12 0 11 0; +#X connect 13 0 8 0; +#X connect 15 0 1 1; +#X connect 16 0 1 1; +#X connect 17 0 1 1; +#X connect 18 0 13 1; +#X connect 19 0 13 1; +#X connect 20 0 13 1; +#X connect 21 0 13 1; diff --git a/test/cyclone/kanon.mid b/test/cyclone/kanon.mid Binary files differnew file mode 100644 index 0000000..a07f5ec --- /dev/null +++ b/test/cyclone/kanon.mid diff --git a/test/cyclone/kink-test.pd b/test/cyclone/kink-test.pd new file mode 100644 index 0000000..44bade7 --- /dev/null +++ b/test/cyclone/kink-test.pd @@ -0,0 +1,22 @@ +#N canvas 289 161 465 369 12; +#X obj 31 88 kink~; +#X floatatom 99 88 0 0 0 0 - - -; +#X obj 32 156 Scope~ 400 200 256 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X obj 30 16 phasor~ 3; +#X obj 30 53 *~ 1; +#X floatatom 100 53 0 0 0 0 - - -; +#X obj 242 53 kink~; +#X floatatom 242 120 5 0 0 0 - - -; +#X floatatom 242 16 5 0 0 0 - - -; +#X floatatom 315 16 5 0 0 0 - - -; +#X obj 242 88 Snapshot~ 10; +#X connect 0 0 2 0; +#X connect 1 0 0 1; +#X connect 3 0 4 0; +#X connect 4 0 0 0; +#X connect 5 0 4 1; +#X connect 6 0 10 0; +#X connect 8 0 6 0; +#X connect 9 0 6 1; +#X connect 10 0 7 0; diff --git a/test/cyclone/line-test.pd b/test/cyclone/line-test.pd new file mode 100644 index 0000000..76df2da --- /dev/null +++ b/test/cyclone/line-test.pd @@ -0,0 +1,54 @@ +#N canvas 95 168 608 427 12; +#X obj 37 222 Line~; +#N canvas 0 0 450 300 graph1 0; +#X array t 133000 float 0; +#X coords 0 1000 132999 -1000 200 140 1; +#X restore 390 37 graph; +#X obj 38 303 tabwrite~ t; +#X obj 37 53 t b b; +#X obj 37 16 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 106 53 t b b; +#X obj 106 16 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 296 380 capture~ f; +#X msg 296 341 clear; +#X obj 61 380 capture~ f; +#X msg 231 341 clear; +#X obj 354 241 Snapshot~ 150; +#X floatatom 354 279 5 0 0 0 - - -; +#X obj 77 268 print; +#X obj 61 341 delay~ 4096 4096; +#X obj 175 53 t b b; +#X obj 175 16 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 37 89 0 \, 1000 1000 0 1000 1000 1000; +#X msg 103 187 0 \, 1000 1; +#X msg 56 120 0 \, 1000 1 0 640 -1000 0 1000 640 0; +#X msg 77 152 0 \, 1000 640; +#X connect 0 0 2 0; +#X connect 0 0 7 0; +#X connect 0 0 11 0; +#X connect 0 0 14 0; +#X connect 0 1 13 0; +#X connect 0 1 10 0; +#X connect 3 0 17 0; +#X connect 3 1 2 0; +#X connect 3 1 8 0; +#X connect 4 0 3 0; +#X connect 5 0 19 0; +#X connect 5 1 2 0; +#X connect 5 1 8 0; +#X connect 6 0 5 0; +#X connect 8 0 7 0; +#X connect 10 0 9 0; +#X connect 11 0 12 0; +#X connect 14 0 9 0; +#X connect 15 0 20 0; +#X connect 15 1 8 0; +#X connect 15 1 2 0; +#X connect 16 0 15 0; +#X connect 17 0 0 0; +#X connect 18 0 0 0; +#X connect 19 0 0 0; +#X connect 20 0 0 0; diff --git a/test/cyclone/match-reentrant.pd b/test/cyclone/match-reentrant.pd new file mode 100644 index 0000000..495cfad --- /dev/null +++ b/test/cyclone/match-reentrant.pd @@ -0,0 +1,20 @@ +#N canvas 496 270 520 430 12; +#X obj 38 135 t a b; +#X obj 38 244 print; +#X obj 38 88 match -1 -2 -3 -4 -5 -6 -7 -8 -9; +#X msg 38 38 -1 -2 -3 -4 -5 -6 -7 -8 -9; +#X msg 78 195 set 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17; +#X obj 228 330 t a b; +#X msg 268 373 4 5 6; +#X obj 228 289 match 1 nn 3; +#X msg 228 244 1 2 3; +#X connect 0 0 1 0; +#X connect 0 1 4 0; +#X connect 2 0 0 0; +#X connect 3 0 2 0; +#X connect 4 0 2 0; +#X connect 5 0 1 0; +#X connect 5 1 6 0; +#X connect 6 0 7 0; +#X connect 7 0 5 0; +#X connect 8 0 7 0; diff --git a/test/cyclone/match-test.pd b/test/cyclone/match-test.pd new file mode 100644 index 0000000..e02a909 --- /dev/null +++ b/test/cyclone/match-test.pd @@ -0,0 +1,33 @@ +#N canvas 79 190 867 561 12; +#X obj 490 63 match; +#X obj 27 182 match one two nn one; +#X obj 29 451 match 0 one two nn one 0; +#X msg 27 26 one two 99 one; +#X msg 47 63 list one two 99 one; +#X msg 66 101 one \, two \, and \, one \, two \, or \, one; +#X msg 82 141 one \, two \, and \, one \, one \, two \, or \, one; +#X msg 29 308 0 \, one \, two \, and \, one \, 0 \, one \, two \, or +\, one \, 0; +#X msg 46 350 0 \, one \, two \, set two three \, three \, set 0 one +two nn one 0; +#X msg 61 392 0 \, one \, two \, set two three \, two \, three \, set +0 one two nn one 0; +#X msg 490 26 test; +#X obj 593 63 match test; +#X msg 593 26 test \, set \, test \, set test; +#X obj 490 101 print; +#X obj 27 226 print; +#X obj 29 494 print; +#X connect 0 0 13 0; +#X connect 1 0 14 0; +#X connect 2 0 15 0; +#X connect 3 0 1 0; +#X connect 4 0 1 0; +#X connect 5 0 1 0; +#X connect 6 0 1 0; +#X connect 7 0 2 0; +#X connect 8 0 2 0; +#X connect 9 0 2 0; +#X connect 10 0 0 0; +#X connect 11 0 13 0; +#X connect 12 0 11 0; diff --git a/test/cyclone/maxmin-test.pd b/test/cyclone/maxmin-test.pd new file mode 100644 index 0000000..278aa8e --- /dev/null +++ b/test/cyclone/maxmin-test.pd @@ -0,0 +1,65 @@ +#N canvas 212 65 529 484 12; +#X obj 82 209 maximum; +#X msg 57 54 1 2 3 4 5 4 3 2 1; +#X floatatom 140 175 5 0 0; +#X floatatom 140 149 5 0 0; +#X floatatom 82 251 5 0 0; +#X msg 21 175 bang; +#X msg 36 23 1 2 3 4 5 5 4 3 2 1; +#X msg 292 54 1 2 3 4 5 4 3 2 1; +#X floatatom 401 175 5 0 0; +#X floatatom 401 149 5 0 0; +#X floatatom 316 251 5 0 0; +#X msg 255 175 bang; +#X msg 270 23 1 2 3 4 5 4 3 2; +#X obj 316 209 minimum -1; +#X msg 82 84 list a b c 4; +#X msg 316 84 list a 2 c 4; +#X msg 103 115 1 b c d; +#X msg 334 115 1 b 3 d; +#X obj 78 365 Peak; +#X floatatom 109 330 5 0 0; +#X floatatom 78 453 5 0 0; +#X obj 93 426 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 109 399 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 +1; +#X msg 42 330 bang; +#X floatatom 109 297 5 0 0; +#X floatatom 306 330 5 0 0; +#X floatatom 257 453 5 0 0; +#X obj 281 426 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 306 399 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 +1; +#X msg 221 330 bang; +#X floatatom 308 297 5 0 0; +#X obj 257 365 Trough; +#X connect 0 0 4 0; +#X connect 1 0 0 0; +#X connect 2 0 0 1; +#X connect 3 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 13 0; +#X connect 8 0 13 1; +#X connect 9 0 13 0; +#X connect 11 0 13 0; +#X connect 12 0 13 0; +#X connect 13 0 10 0; +#X connect 14 0 0 0; +#X connect 15 0 13 0; +#X connect 16 0 0 0; +#X connect 17 0 13 0; +#X connect 18 0 20 0; +#X connect 18 1 21 0; +#X connect 18 2 22 0; +#X connect 19 0 18 1; +#X connect 23 0 18 0; +#X connect 24 0 18 0; +#X connect 25 0 31 1; +#X connect 29 0 31 0; +#X connect 30 0 31 0; +#X connect 31 0 26 0; +#X connect 31 1 27 0; +#X connect 31 2 28 0; diff --git a/test/cyclone/mean-test.pd b/test/cyclone/mean-test.pd new file mode 100644 index 0000000..29fb8a6 --- /dev/null +++ b/test/cyclone/mean-test.pd @@ -0,0 +1,16 @@ +#N canvas 368 260 327 204 12; +#X obj 84 84 mean; +#X msg 141 34 1 2 3 4; +#X msg 233 34 99; +#X floatatom 84 123 5 0 0; +#X floatatom 156 123 5 0 0; +#X msg 21 34 clear; +#X msg 84 34 bang; +#X floatatom 233 64 5 0 0; +#X connect 0 0 3 0; +#X connect 0 1 4 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; diff --git a/test/cyclone/midi-test.pd b/test/cyclone/midi-test.pd new file mode 100644 index 0000000..8846f70 --- /dev/null +++ b/test/cyclone/midi-test.pd @@ -0,0 +1,33 @@ +#N canvas 236 201 400 408 12; +#X obj 207 181 flush; +#X msg 46 29 bang; +#X obj 207 76 midiparse; +#X obj 207 29 midiin; +#X obj 207 283 midiformat; +#X obj 207 234 pack; +#X obj 207 336 midiout; +#X obj 46 181 midiflush; +#X obj 46 128 spigot; +#X obj 207 128 spigot; +#X obj 134 25 tgl 25 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X obj 134 76 == 0; +#X floatatom 46 222 5 0 0; +#X floatatom 294 336 5 0 0; +#X connect 0 0 5 0; +#X connect 0 1 5 1; +#X connect 1 0 9 0; +#X connect 1 0 8 0; +#X connect 2 0 9 0; +#X connect 3 0 8 0; +#X connect 3 0 2 0; +#X connect 4 0 6 0; +#X connect 4 0 13 0; +#X connect 5 0 4 0; +#X connect 7 0 6 0; +#X connect 7 0 12 0; +#X connect 8 0 7 0; +#X connect 9 0 0 0; +#X connect 10 0 8 1; +#X connect 10 0 11 0; +#X connect 11 0 9 1; diff --git a/test/cyclone/midiparse-test.pd b/test/cyclone/midiparse-test.pd new file mode 100644 index 0000000..b006c94 --- /dev/null +++ b/test/cyclone/midiparse-test.pd @@ -0,0 +1,28 @@ +#N canvas 445 218 450 300 12; +#X obj 124 189 midiparse; +#X obj 124 225 funnel 7; +#X obj 124 262 print; +#X msg 124 18 145 \, 0 \, 64; +#X msg 137 44 145 \, 1 \, 0; +#X floatatom 39 18 5 0 0; +#X msg 152 71 128 \, 2 \, 0; +#X msg 44 148 bang; +#X msg 42 71 1 2 3; +#X msg 207 103 248; +#X msg 160 103 240; +#X connect 0 0 1 0; +#X connect 0 1 1 1; +#X connect 0 2 1 2; +#X connect 0 3 1 3; +#X connect 0 4 1 4; +#X connect 0 5 1 5; +#X connect 0 6 1 6; +#X connect 1 0 2 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 0 0; +#X connect 10 0 0 0; diff --git a/test/cyclone/mousefilter-test.pd b/test/cyclone/mousefilter-test.pd new file mode 100644 index 0000000..084086f --- /dev/null +++ b/test/cyclone/mousefilter-test.pd @@ -0,0 +1,28 @@ +#N canvas 199 54 444 300 12; +#X obj 50 198 mousefilter; +#X floatatom 50 158 5 0 0; +#X obj 50 239 print; +#X obj 50 38 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 50 116 random 1000; +#X obj 214 198 mousefilter; +#X floatatom 214 158 5 0 0; +#X obj 214 239 print; +#X obj 214 38 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 214 116 random 1000; +#X obj 50 74 metro 500; +#X obj 214 74 metro 500; +#X obj 341 26 vsl 15 128 0 127 0 0 empty empty empty 0 -8 0 8 -262144 +-1 -1 6800 0; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 10 0; +#X connect 4 0 1 0; +#X connect 5 0 7 0; +#X connect 6 0 5 0; +#X connect 8 0 11 0; +#X connect 9 0 6 0; +#X connect 10 0 4 0; +#X connect 11 0 9 0; +#X connect 12 0 5 0; diff --git a/test/cyclone/next-test.pd b/test/cyclone/next-test.pd new file mode 100644 index 0000000..50d78d1 --- /dev/null +++ b/test/cyclone/next-test.pd @@ -0,0 +1,16 @@ +#N canvas 225 213 485 258 12; +#X obj 91 143 next; +#X msg 91 26 bang \, bang; +#X msg 118 78 bang; +#X obj 236 105 delay 0; +#X msg 236 55 bang; +#X obj 122 177 print same; +#X obj 91 208 print new; +#X text 286 49 this fails without geteventno; +#X connect 0 0 6 0; +#X connect 0 1 5 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 3 0; +#X connect 4 0 0 0; diff --git a/test/cyclone/offer-test.pd b/test/cyclone/offer-test.pd new file mode 100644 index 0000000..537a3b9 --- /dev/null +++ b/test/cyclone/offer-test.pd @@ -0,0 +1,76 @@ +#N canvas 299 297 735 363 12; +#X obj 49 244 offer; +#X floatatom 49 279 5 0 0; +#X msg 50 114 clear; +#X floatatom 172 181 5 0 0; +#X obj 212 244 * -1; +#X obj 172 209 t 0 0; +#X floatatom 172 147 5 0 0; +#X obj 279 110 Uzi; +#X msg 49 181 debug \$1; +#X msg 71 147 1; +#X obj 279 71 t 0 0; +#X msg 224 31 1000; +#X msg 279 31 10000; +#X msg 173 31 100; +#X obj 530 147 counter; +#X obj 530 110 Uzi; +#X msg 595 31 100000; +#X msg 475 31 1000; +#X msg 530 31 10000; +#X msg 424 31 100; +#X msg 578 110 set 0; +#X obj 530 71 t 0 b; +#X msg 114 147 2; +#X obj 279 147 urn; +#X msg 344 31 100000; +#X obj 531 306 counter; +#X obj 531 271 Uzi; +#X msg 579 271 set 0; +#X obj 531 234 t 0 b; +#X msg 531 196 50; +#X msg 582 196 100; +#X obj 429 234 Uzi; +#X msg 429 196 50; +#X msg 480 196 100; +#X obj 429 271 urn 100; +#X msg 117 209 1.5; +#X connect 0 0 1 0; +#X connect 2 0 0 0; +#X connect 3 0 5 0; +#X connect 4 0 0 1; +#X connect 5 0 0 0; +#X connect 5 1 4 0; +#X connect 6 0 0 0; +#X connect 7 0 23 0; +#X connect 8 0 0 0; +#X connect 9 0 8 0; +#X connect 10 0 7 0; +#X connect 10 1 23 1; +#X connect 11 0 10 0; +#X connect 12 0 10 0; +#X connect 13 0 10 0; +#X connect 14 0 5 0; +#X connect 15 0 14 0; +#X connect 16 0 21 0; +#X connect 17 0 21 0; +#X connect 18 0 21 0; +#X connect 19 0 21 0; +#X connect 20 0 14 0; +#X connect 21 0 15 0; +#X connect 21 1 20 0; +#X connect 22 0 8 0; +#X connect 23 0 5 0; +#X connect 24 0 10 0; +#X connect 25 0 0 0; +#X connect 26 0 25 0; +#X connect 27 0 25 0; +#X connect 28 0 26 0; +#X connect 28 1 27 0; +#X connect 29 0 28 0; +#X connect 30 0 28 0; +#X connect 31 0 34 0; +#X connect 32 0 31 0; +#X connect 33 0 31 0; +#X connect 34 0 0 0; +#X connect 35 0 0 0; diff --git a/test/cyclone/onebang-test.pd b/test/cyclone/onebang-test.pd new file mode 100644 index 0000000..56f0440 --- /dev/null +++ b/test/cyclone/onebang-test.pd @@ -0,0 +1,26 @@ +#N canvas 516 361 450 300 12; +#X obj 65 144 onebang; +#X obj 65 89 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 65 200 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 221 89 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 221 200 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 221 144 onebang 1; +#X obj 123 109 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 297 109 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 297 62 metro 500; +#X obj 297 24 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 5 0; +#X connect 5 0 4 0; +#X connect 6 0 0 1; +#X connect 7 0 5 1; +#X connect 8 0 5 0; +#X connect 9 0 8 0; diff --git a/test/cyclone/past-test.pd b/test/cyclone/past-test.pd new file mode 100644 index 0000000..3c1b1c5 --- /dev/null +++ b/test/cyclone/past-test.pd @@ -0,0 +1,38 @@ +#N canvas 280 124 570 391 12; +#X obj 56 244 print; +#X floatatom 56 109 5 0 0; +#X obj 185 244 print; +#X floatatom 185 109 5 0 0; +#X obj 185 198 past 1 2 3; +#X obj 296 244 print; +#X obj 296 198 past 1 2 3; +#X msg 317 128 2 3 4; +#X msg 309 93 1 2 3; +#X msg 296 53 0 1 2; +#X msg 121 109 clear; +#X msg 121 138 set 3; +#X obj 56 198 past 7; +#X msg 245 53 0; +#X msg 121 167 set 7; +#X msg 402 157 2 0 0 \, 1 2 3; +#X msg 402 128 0 3 4 \, 1 2 3; +#X msg 401 93 2 3 0; +#X msg 461 93 1 1 4; +#X msg 283 13 set 1 2 3 4 5 6 7 8 9; +#X connect 1 0 12 0; +#X connect 3 0 4 0; +#X connect 4 0 2 0; +#X connect 6 0 5 0; +#X connect 7 0 6 0; +#X connect 8 0 6 0; +#X connect 9 0 6 0; +#X connect 10 0 12 0; +#X connect 11 0 12 0; +#X connect 12 0 0 0; +#X connect 13 0 6 0; +#X connect 14 0 12 0; +#X connect 15 0 6 0; +#X connect 16 0 6 0; +#X connect 17 0 6 0; +#X connect 18 0 6 0; +#X connect 19 0 6 0; diff --git a/test/cyclone/peakamp-test.pd b/test/cyclone/peakamp-test.pd new file mode 100644 index 0000000..c0c3121 --- /dev/null +++ b/test/cyclone/peakamp-test.pd @@ -0,0 +1,25 @@ +#N canvas 354 192 367 254 12; +#X obj 190 160 peakamp~ 1; +#X obj 31 82 count~ 0 64 1 1; +#X obj 31 225 capture~; +#X msg 190 124 bang; +#X floatatom 126 225 5 0 0 0 - - -; +#X obj 190 221 capture 1000; +#X msg 31 47 min \$1; +#X floatatom 31 16 5 0 0 0 - - -; +#X floatatom 161 16 5 0 0 0 - - -; +#X msg 59 192 open; +#X obj 59 160 delay 0; +#X msg 59 124 bang; +#X connect 0 0 4 0; +#X connect 0 0 5 0; +#X connect 1 0 0 0; +#X connect 1 0 2 0; +#X connect 3 0 0 0; +#X connect 6 0 1 0; +#X connect 7 0 6 0; +#X connect 8 0 1 1; +#X connect 9 0 2 0; +#X connect 9 0 5 0; +#X connect 10 0 9 0; +#X connect 11 0 10 0; diff --git a/test/cyclone/peek-test.pd b/test/cyclone/peek-test.pd new file mode 100644 index 0000000..ef0db24 --- /dev/null +++ b/test/cyclone/peek-test.pd @@ -0,0 +1,51 @@ +#N canvas 326 171 584 586 12; +#N canvas 0 0 450 300 graph1 0; +#X array 0-t 20000 float 0; +#X coords 0 1 19999 -1 200 140 1; +#X restore 59 17 graph; +#N canvas 0 0 450 300 graph1 0; +#X array 1-t 20000 float 0; +#X coords 0 1 19999 -1 200 140 1; +#X restore 326 17 graph; +#X obj 122 511 peek~ t 1; +#X floatatom 122 548 5 0 0; +#X msg 286 362 1; +#X msg 286 394 2; +#X msg 286 430 3; +#X msg 286 326 0; +#X floatatom 390 548 5 0 0; +#X floatatom 390 438 5 0 0; +#X floatatom 428 469 5 0 0; +#X obj 390 511 peek~ 0-t; +#X floatatom 122 438 5 0 0; +#X floatatom 160 474 5 0 0; +#X floatatom 41 253 5 0 0; +#X obj 41 400 pack 0 0 0; +#X floatatom 171 362 5 0 0; +#X obj 41 287 t 0 b; +#X obj 81 326 random 1000; +#X obj 41 438 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X msg 41 474 clip \$1; +#X obj 81 362 / -500; +#X floatatom 150 400 5 0 0; +#X connect 2 0 3 0; +#X connect 4 0 2 2; +#X connect 5 0 2 2; +#X connect 6 0 2 2; +#X connect 7 0 2 2; +#X connect 9 0 11 0; +#X connect 10 0 11 1; +#X connect 11 0 8 0; +#X connect 12 0 2 0; +#X connect 13 0 2 1; +#X connect 14 0 17 0; +#X connect 15 0 2 0; +#X connect 16 0 15 2; +#X connect 17 0 15 0; +#X connect 17 1 18 0; +#X connect 18 0 21 0; +#X connect 19 0 20 0; +#X connect 20 0 2 0; +#X connect 21 0 15 1; +#X connect 21 0 22 0; diff --git a/test/cyclone/prepend-test.pd b/test/cyclone/prepend-test.pd new file mode 100644 index 0000000..d43b8c1 --- /dev/null +++ b/test/cyclone/prepend-test.pd @@ -0,0 +1,73 @@ +#N canvas 479 230 524 465 12; +#X obj 25 416 print; +#X msg 25 298 1 2 3; +#X msg 102 298 set test; +#X obj 25 241 print; +#X msg 25 55 1 2 3; +#X obj 25 169 t a b; +#X msg 111 241 4 5 6; +#X obj 190 206 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 347 55 testmess 1000; +#X msg 347 19 mess; +#X msg 101 19 mess; +#X obj 101 55 testmess 100; +#X msg 155 128 set changed; +#X obj 111 169 gate; +#X obj 111 206 t b b; +#X obj 25 377 t a b b; +#X msg 220 416 set mess1; +#X msg 108 416 set mess2; +#X msg 285 241 bang; +#X msg 347 241 99; +#X obj 285 377 print list; +#X obj 285 339 route list; +#X obj 408 377 print; +#X msg 227 241 mess; +#X obj 25 128 prepend test; +#X obj 25 339 prepend test; +#X msg 398 241 set bang; +#X msg 400 278 set 0; +#X obj 285 298 prepend; +#X obj 101 88 prepend check; +#X obj 347 88 prepend check; +#X msg 160 19 set set; +#X msg 244 19 set check; +#X msg 348 211 list; +#X connect 1 0 25 0; +#X connect 2 0 25 0; +#X connect 4 0 24 0; +#X connect 5 0 3 0; +#X connect 5 1 13 1; +#X connect 6 0 24 0; +#X connect 7 0 13 0; +#X connect 8 0 30 0; +#X connect 9 0 8 0; +#X connect 10 0 11 0; +#X connect 11 0 29 0; +#X connect 12 0 24 0; +#X connect 13 0 14 0; +#X connect 14 0 6 0; +#X connect 14 1 7 0; +#X connect 15 0 0 0; +#X connect 15 1 17 0; +#X connect 15 2 16 0; +#X connect 16 0 25 0; +#X connect 17 0 25 0; +#X connect 18 0 28 0; +#X connect 19 0 28 0; +#X connect 21 0 20 0; +#X connect 21 1 22 0; +#X connect 23 0 28 0; +#X connect 24 0 5 0; +#X connect 25 0 15 0; +#X connect 26 0 28 0; +#X connect 27 0 28 0; +#X connect 28 0 21 0; +#X connect 29 0 24 0; +#X connect 30 0 24 0; +#X connect 31 0 30 0; +#X connect 31 0 29 0; +#X connect 32 0 30 0; +#X connect 32 0 29 0; +#X connect 33 0 28 0; diff --git a/test/cyclone/prob-test.pd b/test/cyclone/prob-test.pd new file mode 100644 index 0000000..e21a3c5 --- /dev/null +++ b/test/cyclone/prob-test.pd @@ -0,0 +1,33 @@ +#N canvas 482 332 476 300 12; +#X obj 146 119 anal; +#X obj 146 174 prob; +#X floatatom 114 221 5 0 0; +#X obj 213 221 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 146 84 5 0 0; +#X msg 52 139 dump; +#X msg 125 48 bang; +#X floatatom 222 84 5 0 0; +#X msg 297 84 2 -1 1; +#X msg 359 119 reset 2; +#X msg 51 84 embed 1; +#X msg 221 48 clear; +#X msg 298 48 -1; +#X msg 375 84 1 1 1; +#X msg 344 48 1; +#X msg 47 14 clear \, 2 -1 1 \, -1 \, bang \, reset 2; +#X connect 0 0 1 0; +#X connect 1 0 2 0; +#X connect 1 1 3 0; +#X connect 4 0 0 0; +#X connect 5 0 1 0; +#X connect 6 0 1 0; +#X connect 7 0 1 0; +#X connect 8 0 1 0; +#X connect 9 0 1 0; +#X connect 10 0 1 0; +#X connect 11 0 1 0; +#X connect 12 0 1 0; +#X connect 13 0 1 0; +#X connect 14 0 1 0; +#X connect 15 0 1 0; diff --git a/test/cyclone/pv-test.pd b/test/cyclone/pv-test.pd new file mode 100644 index 0000000..c1252b5 --- /dev/null +++ b/test/cyclone/pv-test.pd @@ -0,0 +1,83 @@ +#N canvas 400 284 560 390 12; +#X obj 53 112 pv x; +#X floatatom 53 77 5 0 0; +#X msg 132 40 bang; +#X floatatom 132 112 5 0 0; +#X msg 197 40 status; +#X msg 29 40 status; +#X floatatom 57 238 5 0 0; +#X msg 286 238 bang; +#X msg 351 238 status; +#X msg 32 190 status; +#X obj 286 280 pv common; +#N canvas 556 81 496 259 sub-a 0; +#X floatatom 59 88 5 0 0; +#X msg 317 88 bang; +#X msg 382 88 status; +#X msg 35 51 status; +#X obj 317 123 pv common; +#X msg 133 88 bang; +#X floatatom 250 88 5 0 0; +#X obj 59 161 print private-a; +#X obj 317 161 print common-a; +#X obj 59 123 pv private symbol test; +#X connect 0 0 9 0; +#X connect 1 0 4 0; +#X connect 2 0 4 0; +#X connect 3 0 9 0; +#X connect 4 0 8 0; +#X connect 5 0 9 0; +#X connect 6 0 4 0; +#X connect 9 0 7 0; +#X restore 454 280 pd sub-a; +#X msg 455 64 \; x bang; +#X obj 455 148 r x; +#X obj 455 190 print; +#N canvas 556 81 496 259 sub-b 0; +#X floatatom 91 87 5 0 0; +#X msg 317 87 bang; +#X msg 382 87 status; +#X msg 67 50 status; +#X obj 317 122 pv common; +#X msg 165 87 bang; +#X floatatom 250 87 5 0 0; +#X obj 91 160 print private-b; +#X obj 317 160 print common-b; +#X obj 91 122 pv private 1 2 3; +#X connect 0 0 9 0; +#X connect 1 0 4 0; +#X connect 2 0 4 0; +#X connect 3 0 9 0; +#X connect 4 0 8 0; +#X connect 5 0 9 0; +#X connect 6 0 4 0; +#X connect 9 0 7 0; +#X restore 453 318 pd sub-b; +#X obj 286 318 print common; +#X msg 116 190 symbol test; +#X obj 288 195 testmess 100; +#X msg 288 159 bang; +#X msg 344 159 test; +#X msg 288 88 bang; +#X msg 344 88 test; +#X obj 288 124 testmess 300; +#X obj 57 280 pv common test message; +#X obj 132 77 pv x 99; +#X connect 1 0 0 0; +#X connect 2 0 25 0; +#X connect 4 0 25 0; +#X connect 5 0 0 0; +#X connect 6 0 24 0; +#X connect 7 0 10 0; +#X connect 8 0 10 0; +#X connect 9 0 24 0; +#X connect 10 0 16 0; +#X connect 13 0 14 0; +#X connect 17 0 24 0; +#X connect 18 0 24 0; +#X connect 19 0 18 0; +#X connect 20 0 18 0; +#X connect 21 0 23 0; +#X connect 22 0 23 0; +#X connect 23 0 24 0; +#X connect 25 0 3 0; diff --git a/test/cyclone/rand-test.pd b/test/cyclone/rand-test.pd new file mode 100644 index 0000000..2a438d6 --- /dev/null +++ b/test/cyclone/rand-test.pd @@ -0,0 +1,37 @@ +#N canvas 224 159 762 415 12; +#X obj 33 348 tabwrite~ t; +#N canvas 0 0 450 300 graph1 0; +#X array t 400 float 0; +#X coords 0 1 399 -1 400 300 1; +#X restore 330 44 graph; +#X obj 35 54 osc~ 10; +#X obj 35 89 *~ 1000; +#X floatatom 35 19 5 0 0 0 - - -; +#X obj 256 174 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X floatatom 114 54 5 0 0 0 - - -; +#X msg 64 189 \$1 \; pd dsp \$1; +#X obj 45 244 metro 300; +#X obj 33 151 rand~ 1000; +#X floatatom 168 114 5 0 0 0 - - -; +#X obj 171 315 hsl 128 15 -1 1 0 0 empty empty empty -2 -6 0 8 -262144 +-1 -1 0 1; +#X obj 168 151 rand~; +#X obj 64 315 capture~ f; +#X msg 64 278 clear; +#X obj 177 204 sel 1; +#X obj 168 278 Snapshot~ 20; +#X connect 2 0 3 0; +#X connect 4 0 2 0; +#X connect 5 0 7 0; +#X connect 5 0 15 0; +#X connect 6 0 3 1; +#X connect 7 0 8 0; +#X connect 8 0 0 0; +#X connect 9 0 0 0; +#X connect 9 0 13 0; +#X connect 10 0 12 0; +#X connect 12 0 16 0; +#X connect 14 0 13 0; +#X connect 15 0 14 0; +#X connect 16 0 11 0; diff --git a/test/cyclone/record-sync-test.pd b/test/cyclone/record-sync-test.pd new file mode 100644 index 0000000..368bf06 --- /dev/null +++ b/test/cyclone/record-sync-test.pd @@ -0,0 +1,64 @@ +#N canvas 380 162 635 531 12; +#X obj 56 320 record~ t; +#N canvas 0 0 450 300 graph1 0; +#X array t 100000 float 0; +#X coords 0 1 99999 -1 200 140 1; +#X restore 46 20 graph; +#X floatatom 77 241 5 0 0; +#X floatatom 149 241 5 0 0; +#X obj 345 279 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 +1; +#X obj 56 437 threshold~ 0; +#X obj 56 401 -~; +#X obj 56 365 delay~ 1 1; +#N canvas 0 0 450 300 graph1 0; +#X array sync 100000 float 0; +#X coords 0 1 99999 -1 200 140 1; +#X restore 299 20 graph; +#X floatatom 400 324 5 0 0; +#X floatatom 400 246 5 0 0; +#X msg 56 205 loop \$1; +#X msg 161 205 append \$1; +#X obj 56 179 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 1 +; +#X obj 161 179 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 0 +1; +#X obj 56 476 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 149 279 / 44.1; +#X obj 77 279 / 44.1; +#X obj 345 365 record~ sync; +#X obj 400 286 tabread sync; +#X msg 303 189 \; sync const 0; +#X obj 240 437 snapshot~; +#X obj 240 401 metro 10; +#X floatatom 240 476 5 0 0; +#X obj 240 369 tgl 15 0 empty empty empty 20 8 0 8 -262144 -1 -1 1 +1; +#X obj 345 437 snapshot~; +#X floatatom 345 476 5 0 0; +#X connect 0 0 6 1; +#X connect 0 0 7 0; +#X connect 0 0 18 0; +#X connect 0 0 21 0; +#X connect 2 0 17 0; +#X connect 3 0 16 0; +#X connect 4 0 0 0; +#X connect 4 0 18 0; +#X connect 5 0 15 0; +#X connect 6 0 5 0; +#X connect 7 0 6 0; +#X connect 10 0 19 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 13 0 11 0; +#X connect 14 0 12 0; +#X connect 16 0 0 2; +#X connect 17 0 0 1; +#X connect 18 0 25 0; +#X connect 19 0 9 0; +#X connect 21 0 23 0; +#X connect 22 0 21 0; +#X connect 22 0 25 0; +#X connect 24 0 22 0; +#X connect 25 0 26 0; diff --git a/test/cyclone/record-test.pd b/test/cyclone/record-test.pd new file mode 100644 index 0000000..8896aec --- /dev/null +++ b/test/cyclone/record-test.pd @@ -0,0 +1,60 @@ +#N canvas 106 146 768 968 12; +#X obj 254 110 record~ bulk 8; +#X obj 53 36 osc~ 1; +#X obj 124 36 osc~ 2; +#X obj 193 36 osc~ 3; +#X obj 263 36 osc~ 4; +#X obj 335 36 osc~ 5; +#X obj 403 36 osc~ 6; +#X obj 479 36 osc~ 7; +#X obj 549 36 osc~ 8; +#X obj 154 95 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#N canvas 0 0 450 300 graph65 0; +#X array 0-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 84 192 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 1-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 84 269 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 2-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 83 345 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 3-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 83 422 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 4-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 83 501 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 5-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 83 578 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 6-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 82 654 graph; +#N canvas 0 0 450 300 graph65 0; +#X array 7-bulk 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 82 731 graph; +#X obj 254 146 record~ sync; +#N canvas 0 0 450 300 graph65 0; +#X array sync 10000 float 0; +#X coords 0 1 9999 -1 600 60 1; +#X restore 80 839 graph; +#X connect 0 0 18 0; +#X connect 1 0 0 0; +#X connect 2 0 0 1; +#X connect 3 0 0 2; +#X connect 4 0 0 3; +#X connect 5 0 0 4; +#X connect 6 0 0 5; +#X connect 7 0 0 6; +#X connect 8 0 0 7; +#X connect 9 0 0 0; +#X connect 9 0 18 0; diff --git a/test/cyclone/scope-gop.pd b/test/cyclone/scope-gop.pd new file mode 100644 index 0000000..a5980d0 --- /dev/null +++ b/test/cyclone/scope-gop.pd @@ -0,0 +1,2 @@ +#N canvas 315 186 464 344 12; +#X obj 186 108 scope-test; diff --git a/test/cyclone/scope-test.pd b/test/cyclone/scope-test.pd new file mode 100644 index 0000000..8a69d6b --- /dev/null +++ b/test/cyclone/scope-test.pd @@ -0,0 +1,125 @@ +#N canvas 188 168 778 363 12; +#X obj 19 207 Scope~ 130 130 150 3 200 -1 1 100 0 0 0 50 255 0 202 +32 49 0; +#X floatatom 18 18 5 0 0 0 - - -; +#X floatatom 132 18 5 0 0 0 - - -; +#X obj 18 73 *~; +#X msg 100 161 bufsize \$1; +#X floatatom 100 135 5 0 0 0 - - -; +#X floatatom 247 80 5 0 0 0 - - -; +#X floatatom 276 106 5 0 0 0 - - -; +#X floatatom 305 130 5 0 0 0 - - -; +#X floatatom 36 136 5 0 0 0 - - -; +#X floatatom 364 80 5 0 0 0 - - -; +#X floatatom 393 106 5 0 0 0 - - -; +#X floatatom 422 130 5 0 0 0 - - -; +#N canvas 0 0 262 195 frgb 0; +#X obj 17 25 inlet; +#X obj 94 25 inlet; +#X obj 173 25 inlet; +#X obj 17 148 outlet; +#X obj 17 56 bondo 3; +#X obj 17 86 pack 0 0 0; +#X msg 17 116 frgb \$1 \$2 \$3; +#X connect 0 0 4 0; +#X connect 1 0 4 1; +#X connect 2 0 4 2; +#X connect 4 0 5 0; +#X connect 4 1 5 1; +#X connect 4 2 5 2; +#X connect 5 0 6 0; +#X connect 6 0 3 0; +#X restore 247 161 pd frgb; +#N canvas 0 0 250 195 brgb 0; +#X obj 17 25 inlet; +#X obj 94 25 inlet; +#X obj 173 25 inlet; +#X obj 17 148 outlet; +#X msg 17 116 brgb \$1 \$2 \$3; +#X obj 17 56 bondo 3; +#X obj 17 86 pack 0 0 0; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 2 0 5 2; +#X connect 4 0 3 0; +#X connect 5 0 6 0; +#X connect 5 1 6 1; +#X connect 5 2 6 2; +#X connect 6 0 4 0; +#X restore 364 161 pd brgb; +#X obj 18 44 osc~ 5; +#X obj 132 44 osc~ 11; +#X floatatom 100 80 5 0 0 0 - - -; +#X floatatom 167 80 5 0 0 0 - - -; +#N canvas 0 0 262 195 range 0; +#X obj 17 25 inlet; +#X obj 94 25 inlet; +#X obj 17 145 outlet; +#X msg 17 115 range \$1 \$2; +#X obj 17 85 pack; +#X obj 17 55 bondo; +#X connect 0 0 5 0; +#X connect 1 0 5 1; +#X connect 3 0 2 0; +#X connect 4 0 3 0; +#X connect 5 0 4 0; +#X connect 5 1 4 1; +#X restore 100 106 pd range; +#X floatatom 240 18 5 0 0 0 - - -; +#X msg 240 44 delay \$1; +#X floatatom 171 207 5 0 0 0 - - -; +#X obj 171 233 osc~ 5; +#X obj 243 207 Scope~ 130 130 256 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 73 18 5 0 0 0 - - -; +#X floatatom 386 207 5 0 0 0 - - -; +#X obj 386 233 osc~ 5; +#X floatatom 441 207 5 0 0 0 - - -; +#X floatatom 512 18 5 0 0 0 - - -; +#X obj 512 44 pack; +#X floatatom 575 18 5 0 0 0 - - -; +#X msg 512 73 triglevel \$1 \, trigger \$2; +#X obj 512 207 Scope~ 130 130 256 3 128 -1 1 300 0 1 0 253 86 245 17 +40 152 0; +#X floatatom 655 136 5 0 0 0 - - -; +#X floatatom 731 136 5 0 0 0 - - -; +#X floatatom 530 136 5 0 0 0 - - -; +#X msg 530 162 delay \$1; +#X obj 655 162 osc~ 1.35; +#X connect 1 0 15 0; +#X connect 2 0 16 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 4 0; +#X connect 6 0 13 0; +#X connect 7 0 13 1; +#X connect 8 0 13 2; +#X connect 9 0 0 0; +#X connect 10 0 14 0; +#X connect 11 0 14 1; +#X connect 12 0 14 2; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 15 0 3 0; +#X connect 16 0 3 1; +#X connect 17 0 19 0; +#X connect 18 0 19 1; +#X connect 19 0 0 0; +#X connect 20 0 21 0; +#X connect 21 0 0 0; +#X connect 22 0 23 0; +#X connect 23 0 24 0; +#X connect 25 0 15 1; +#X connect 26 0 27 0; +#X connect 27 0 24 1; +#X connect 28 0 27 1; +#X connect 29 0 30 0; +#X connect 30 0 32 0; +#X connect 31 0 30 1; +#X connect 32 0 33 0; +#X connect 34 0 38 0; +#X connect 35 0 38 1; +#X connect 36 0 37 0; +#X connect 37 0 33 0; +#X connect 38 0 33 0; +#X coords 0 0 1 1 200 140 1; diff --git a/test/cyclone/scope-test1.pd b/test/cyclone/scope-test1.pd new file mode 100644 index 0000000..60af46d --- /dev/null +++ b/test/cyclone/scope-test1.pd @@ -0,0 +1,28 @@ +#N canvas 236 201 450 300 12; +#X obj 17 27 osc~ 440; +#X obj 15 250 dac~; +#X obj 16 190 *~ 0.1; +#X obj 177 135 Scope~ 252 152 10 3 100 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 177 96 5 0 0 0 - - -; +#X msg 270 96 bufsize \$1; +#X floatatom 270 60 5 0 0 0 - - -; +#X msg 177 21 10; +#X msg 270 21 100; +#X obj 38 96 triangle~; +#X obj 17 141 *~; +#X floatatom 107 27 5 0 0 0 - - -; +#X obj 38 60 phasor~ 4; +#X connect 0 0 10 0; +#X connect 2 0 1 0; +#X connect 2 0 1 1; +#X connect 4 0 3 0; +#X connect 5 0 3 0; +#X connect 6 0 5 0; +#X connect 7 0 4 0; +#X connect 8 0 6 0; +#X connect 9 0 10 1; +#X connect 10 0 2 0; +#X connect 10 0 3 0; +#X connect 11 0 12 0; +#X connect 12 0 9 0; diff --git a/test/cyclone/scope-test2.pd b/test/cyclone/scope-test2.pd new file mode 100644 index 0000000..47ad604 --- /dev/null +++ b/test/cyclone/scope-test2.pd @@ -0,0 +1,31 @@ +#N canvas 495 177 450 300 12; +#X obj 15 250 dac~; +#X obj 16 190 *~ 0.1; +#X obj 177 135 Scope~ 252 152 30 3 250 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 177 96 5 0 0 0 - - -; +#X msg 270 96 bufsize \$1; +#X floatatom 270 60 5 0 0 0 - - -; +#X obj 38 96 triangle~; +#X obj 17 141 *~; +#X floatatom 107 27 5 0 0 0 - - -; +#X obj 17 27 osc~ 110; +#X obj 38 60 phasor~ 111; +#X msg 177 21 30; +#X msg 270 21 250; +#X msg 195 60 4; +#X connect 1 0 0 0; +#X connect 1 0 0 1; +#X connect 3 0 2 0; +#X connect 4 0 2 0; +#X connect 5 0 4 0; +#X connect 6 0 7 1; +#X connect 6 0 2 1; +#X connect 7 0 1 0; +#X connect 7 0 2 0; +#X connect 8 0 10 0; +#X connect 9 0 7 0; +#X connect 10 0 6 0; +#X connect 11 0 3 0; +#X connect 12 0 5 0; +#X connect 13 0 3 0; diff --git a/test/cyclone/seq-test.pd b/test/cyclone/seq-test.pd new file mode 100644 index 0000000..baa645d --- /dev/null +++ b/test/cyclone/seq-test.pd @@ -0,0 +1,58 @@ +#N canvas 349 176 601 359 12; +#X obj 125 191 seq; +#X msg 61 249 print; +#X floatatom 63 83 5 0 0 0 - - -; +#X msg 160 74 record; +#X msg 144 48 stop; +#X msg 217 180 read nosuchfile; +#X obj 125 249 print; +#X obj 125 24 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 217 206 write; +#X msg 379 215 write; +#X msg 168 102 144; +#X msg 217 102 240; +#X obj 61 147 midiin; +#X obj 379 249 seq test.seq; +#X obj 242 319 midiout; +#X msg 217 128 read test.seq; +#X msg 445 215 start \$1; +#X msg 445 147 512; +#X floatatom 445 183 5 0 0 0 - - -; +#X msg 379 147 stop; +#X msg 217 232 write test.seq; +#X obj 242 293 midiflush; +#X msg 189 293 bang; +#X msg 264 102 read kanon.mid; +#X msg 231 74 append; +#X msg 217 258 write test.mid; +#X msg 217 154 read test.mid; +#X connect 0 0 6 0; +#X connect 0 0 21 0; +#X connect 0 1 6 0; +#X connect 1 0 0 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 4 0 22 0; +#X connect 5 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 13 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 12 0 14 0; +#X connect 13 0 21 0; +#X connect 15 0 0 0; +#X connect 16 0 13 0; +#X connect 17 0 18 0; +#X connect 18 0 16 0; +#X connect 19 0 13 0; +#X connect 20 0 0 0; +#X connect 21 0 14 0; +#X connect 22 0 21 0; +#X connect 23 0 0 0; +#X connect 24 0 0 0; +#X connect 25 0 0 0; +#X connect 26 0 0 0; diff --git a/test/cyclone/sigbits-test.pd b/test/cyclone/sigbits-test.pd new file mode 100644 index 0000000..9fcb65d --- /dev/null +++ b/test/cyclone/sigbits-test.pd @@ -0,0 +1,157 @@ +#N canvas 138 178 832 338 12; +#X floatatom 208 168 5 0 0 0 - - -; +#X floatatom 266 155 5 0 0 0 - - -; +#X obj 208 250 Snapshot~ 50; +#X floatatom 208 290 0 0 0 0 - - -; +#X msg 332 168 mode \$1; +#X floatatom 332 134 5 0 0 0 - - -; +#X obj 62 207 bitand~; +#X floatatom 62 168 5 0 0 0 - - -; +#X obj 62 250 Snapshot~ 50; +#X floatatom 62 290 0 0 0 0 - - -; +#X msg 126 168 mode \$1; +#X floatatom 126 134 5 0 0 0 - - -; +#X obj 62 104 prepend bits; +#X obj 62 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 83 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 103 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 123 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 143 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 163 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 183 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 203 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 223 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 243 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 263 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 283 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 303 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 323 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 343 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 363 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 385 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 405 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 425 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 445 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 465 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 485 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 505 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 525 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 545 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 565 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 585 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 605 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 625 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 645 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 665 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 685 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 62 57 pack 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0; +#X obj 26 57 int; +#X obj 26 29 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 419 168 5 0 0 0 - - -; +#X obj 419 250 Snapshot~ 50; +#X floatatom 419 290 0 0 0 0 - - -; +#X msg 489 168 mode \$1; +#X floatatom 489 134 5 0 0 0 - - -; +#X obj 419 214 bitnot~; +#X obj 208 214 bitxor~; +#X floatatom 577 168 5 0 0 0 - - -; +#X obj 577 250 Snapshot~ 50; +#X floatatom 577 290 0 0 0 0 - - -; +#X msg 647 168 mode \$1; +#X floatatom 647 134 5 0 0 0 - - -; +#X msg 683 214 shift \$1; +#X obj 577 214 bitshift~; +#X floatatom 731 168 5 0 0 0 - - -; +#X connect 0 0 54 0; +#X connect 1 0 54 1; +#X connect 2 0 3 0; +#X connect 4 0 54 0; +#X connect 5 0 4 0; +#X connect 6 0 8 0; +#X connect 7 0 6 0; +#X connect 8 0 9 0; +#X connect 10 0 6 0; +#X connect 11 0 10 0; +#X connect 12 0 6 0; +#X connect 13 0 46 1; +#X connect 14 0 45 1; +#X connect 15 0 45 2; +#X connect 16 0 45 3; +#X connect 17 0 45 4; +#X connect 18 0 45 5; +#X connect 19 0 45 6; +#X connect 20 0 45 7; +#X connect 21 0 45 8; +#X connect 22 0 45 9; +#X connect 23 0 45 10; +#X connect 24 0 45 11; +#X connect 25 0 45 12; +#X connect 26 0 45 13; +#X connect 27 0 45 14; +#X connect 28 0 45 15; +#X connect 29 0 45 16; +#X connect 30 0 45 17; +#X connect 31 0 45 18; +#X connect 32 0 45 19; +#X connect 33 0 45 20; +#X connect 34 0 45 21; +#X connect 35 0 45 22; +#X connect 36 0 45 23; +#X connect 37 0 45 24; +#X connect 38 0 45 25; +#X connect 39 0 45 26; +#X connect 40 0 45 27; +#X connect 41 0 45 28; +#X connect 42 0 45 29; +#X connect 43 0 45 30; +#X connect 44 0 45 31; +#X connect 45 0 12 0; +#X connect 46 0 45 0; +#X connect 47 0 46 0; +#X connect 48 0 53 0; +#X connect 49 0 50 0; +#X connect 51 0 53 0; +#X connect 52 0 51 0; +#X connect 53 0 49 0; +#X connect 54 0 2 0; +#X connect 55 0 61 0; +#X connect 56 0 57 0; +#X connect 58 0 61 0; +#X connect 59 0 58 0; +#X connect 60 0 61 0; +#X connect 61 0 56 0; +#X connect 62 0 60 0; diff --git a/test/cyclone/sigcapture-test.pd b/test/cyclone/sigcapture-test.pd new file mode 100644 index 0000000..2225e61 --- /dev/null +++ b/test/cyclone/sigcapture-test.pd @@ -0,0 +1,25 @@ +#N canvas 249 232 527 300 12; +#X obj 200 34 phasor~ 1; +#X floatatom 45 34 5 0 0 0 - - -; +#X msg 306 34 clear; +#X msg 306 69 write; +#X obj 199 107 capture~ 1000 7; +#X obj 47 215 *~ 100; +#X obj 47 256 capture~ 1000 0; +#X obj 47 174 osc~ 100; +#X msg 76 69 clear; +#X obj 45 107 capture~ f; +#X obj 225 215 count~; +#X obj 225 174 bang~; +#X obj 225 256 capture~ 100 0 3 5 7 11 999 13; +#X obj 328 234 capture~ 1000; +#X connect 0 0 4 0; +#X connect 1 0 9 0; +#X connect 2 0 4 0; +#X connect 3 0 4 0; +#X connect 5 0 6 0; +#X connect 7 0 5 0; +#X connect 8 0 9 0; +#X connect 10 0 12 0; +#X connect 10 0 13 0; +#X connect 11 0 10 0; diff --git a/test/cyclone/sigcycle-test.pd b/test/cyclone/sigcycle-test.pd new file mode 100644 index 0000000..9903487 --- /dev/null +++ b/test/cyclone/sigcycle-test.pd @@ -0,0 +1,156 @@ +#N canvas 442 270 466 287 12; +#N canvas 179 250 728 409 test1 0; +#X obj 27 146 cycle~; +#X obj 28 225 Scope~ 301 138 126 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X obj 368 225 Scope~ 301 138 126 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 239 58 5 0 0 0 - - -; +#X floatatom 150 146 5 0 0 0 - - -; +#X msg 233 146 trigger \$1; +#X obj 233 118 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 76 102 phasor~ 3; +#X obj 367 146 cycle~ 3; +#N canvas 0 0 450 300 graph1 0; +#X array t1 1000 float 0; +#X coords 0 1 999 -1 200 140 1; +#X restore 481 34 graph; +#X msg 137 58 set; +#X msg 27 58 set t1 \$1; +#X floatatom 27 23 5 0 0 0 - - -; +#X connect 0 0 1 0; +#X connect 3 0 7 0; +#X connect 3 0 8 0; +#X connect 4 0 1 0; +#X connect 4 0 2 0; +#X connect 5 0 1 0; +#X connect 5 0 2 0; +#X connect 6 0 5 0; +#X connect 7 0 0 1; +#X connect 8 0 2 0; +#X connect 10 0 0 0; +#X connect 10 0 8 0; +#X connect 11 0 0 0; +#X connect 11 0 8 0; +#X connect 12 0 11 0; +#X restore 42 39 pd test1; +#N canvas 125 182 742 644 test2 0; +#X obj 29 255 Scope~ 301 138 72 3 128 -1 1 0 0 0 0 102 255 51 135 135 +135 0; +#X obj 382 255 Scope~ 301 138 72 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 29 19 5 0 0 0 - - -; +#X floatatom 152 211 5 0 0 0 - - -; +#X msg 235 211 trigger \$1; +#X obj 235 181 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 382 211 cycle~ 3; +#X obj 29 211 cycle~ 3; +#X obj 96 143 cycle~ 3; +#X obj 384 105 cycle~ 3; +#X obj 383 177 +~ 3; +#X obj 384 143 *~ 1; +#X obj 95 177 *~ 1; +#X floatatom 96 19 5 0 0 0 - - -; +#X floatatom 168 19 5 0 0 0 - - -; +#X obj 508 112 *; +#X obj 508 63 bondo; +#X obj 548 90 * 6.28; +#X obj 188 435 Scope~ 301 138 72 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X obj 30 513 phasor~ 3; +#X obj 107 435 osc~ 3; +#X obj 107 474 *~ 1; +#X obj 30 575 cos~; +#X obj 30 544 +~; +#X connect 2 0 10 1; +#X connect 2 0 7 0; +#X connect 2 0 19 0; +#X connect 3 0 0 0; +#X connect 3 0 1 0; +#X connect 3 0 18 0; +#X connect 4 0 0 0; +#X connect 4 0 1 0; +#X connect 4 0 18 0; +#X connect 5 0 4 0; +#X connect 6 0 1 0; +#X connect 7 0 0 0; +#X connect 8 0 12 0; +#X connect 9 0 11 0; +#X connect 10 0 6 0; +#X connect 11 0 10 0; +#X connect 12 0 7 1; +#X connect 13 0 9 0; +#X connect 13 0 8 0; +#X connect 13 0 16 0; +#X connect 13 0 20 0; +#X connect 14 0 12 1; +#X connect 14 0 16 1; +#X connect 14 0 21 1; +#X connect 15 0 11 1; +#X connect 16 0 15 0; +#X connect 16 1 17 0; +#X connect 17 0 15 1; +#X connect 19 0 23 0; +#X connect 20 0 21 0; +#X connect 21 0 23 1; +#X connect 22 0 18 0; +#X connect 23 0 22 0; +#X restore 164 39 pd test2; +#N canvas 180 253 749 421 test3 0; +#X obj 29 255 Scope~ 301 138 118 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X obj 382 255 Scope~ 301 138 118 3 128 -1 1 0 0 0 0 102 255 51 135 +135 135 0; +#X floatatom 29 19 5 0 0 0 - - -; +#X floatatom 152 211 5 0 0 0 - - -; +#X msg 235 211 trigger \$1; +#X obj 235 181 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 +1; +#X obj 382 211 cycle~ 3; +#X obj 29 211 cycle~ 3; +#X obj 383 177 +~ 3; +#X obj 444 140 *~ 1; +#X obj 95 177 *~ 1; +#X floatatom 126 20 5 0 0 0 - - -; +#X obj 508 112 *; +#X obj 508 63 bondo; +#X obj 548 90 * 6.28; +#X obj 47 138 delwrite~ d1; +#X obj 174 138 delread~ d1; +#X obj 258 90 delwrite~ d2; +#X obj 385 90 delread~ d2; +#X connect 2 0 8 1; +#X connect 2 0 7 0; +#X connect 2 0 13 0; +#X connect 3 0 0 0; +#X connect 3 0 1 0; +#X connect 4 0 0 0; +#X connect 4 0 1 0; +#X connect 5 0 4 0; +#X connect 6 0 1 0; +#X connect 6 0 17 0; +#X connect 7 0 0 0; +#X connect 7 0 15 0; +#X connect 8 0 6 0; +#X connect 9 0 8 0; +#X connect 10 0 7 1; +#X connect 11 0 10 1; +#X connect 11 0 13 1; +#X connect 12 0 9 1; +#X connect 13 0 12 0; +#X connect 13 1 14 0; +#X connect 14 0 12 1; +#X connect 16 0 10 0; +#X connect 18 0 9 0; +#X restore 293 39 pd test3; +#X floatatom 120 99 5 0 0 0 - - -; +#X floatatom 44 216 0 0 0 0 - - -; +#X msg 44 99 set; +#X obj 44 137 cycle~ t2; +#X obj 44 177 Snapshot~ 20; +#X connect 3 0 6 1; +#X connect 5 0 6 0; +#X connect 6 0 7 0; +#X connect 7 0 4 0; diff --git a/test/cyclone/sigmeters-test.pd b/test/cyclone/sigmeters-test.pd new file mode 100644 index 0000000..edf97e8 --- /dev/null +++ b/test/cyclone/sigmeters-test.pd @@ -0,0 +1,45 @@ +#N canvas 296 215 621 370 12; +#X obj 146 187 minmax~; +#X floatatom 146 29 5 0 0 0 - - -; +#X obj 117 29 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 57 29 reset; +#X obj 204 221 print; +#X obj 174 71 abs~; +#X obj 365 92 avg~; +#X floatatom 365 124 5 0 0 0 - - -; +#X obj 365 29 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 287 60 osc~ 1; +#X obj 365 60 metro 250; +#X obj 164 255 Snapshot~ 150; +#X floatatom 164 287 5 0 0 0 - - -; +#X obj 29 255 Snapshot~ 150; +#X floatatom 29 287 5 0 0 0 - - -; +#X obj 174 106 Snapshot~ 150; +#X floatatom 174 138 5 0 0 0 - - -; +#X floatatom 287 29 5 0 0 0 - - -; +#X obj 367 187 osc~ 100; +#X floatatom 367 257 5 0 0 0 - - -; +#X obj 367 221 average~ 10000 rms; +#X msg 459 187 absolute; +#X connect 0 0 13 0; +#X connect 0 1 11 0; +#X connect 0 2 4 0; +#X connect 0 3 4 0; +#X connect 1 0 0 0; +#X connect 1 0 5 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 5 0 15 0; +#X connect 6 0 7 0; +#X connect 8 0 10 0; +#X connect 9 0 6 0; +#X connect 10 0 6 0; +#X connect 11 0 12 0; +#X connect 13 0 14 0; +#X connect 15 0 16 0; +#X connect 17 0 9 0; +#X connect 18 0 20 0; +#X connect 20 0 19 0; +#X connect 21 0 20 0; diff --git a/test/cyclone/sigops-test.pd b/test/cyclone/sigops-test.pd new file mode 100644 index 0000000..d2eb9a1 --- /dev/null +++ b/test/cyclone/sigops-test.pd @@ -0,0 +1,64 @@ +#N canvas 281 205 642 407 12; +#X obj 25 108 %~; +#X floatatom 25 181 10 0 0 0 - - -; +#X floatatom 25 40 5 0 0 0 - - -; +#X floatatom 96 71 5 0 0 0 - - -; +#X obj 25 71 * 0.01; +#X floatatom 277 40 5 0 0 0 - - -; +#X obj 277 71 +=~; +#X floatatom 277 144 10 0 0 0 - - -; +#X msg 337 40 set 999; +#X msg 222 40 bang; +#X floatatom 442 144 10 0 0 0 - - -; +#X floatatom 442 40 5 0 0 0 - - -; +#X floatatom 513 40 5 0 0 0 - - -; +#X obj 442 71 !/~; +#X obj 277 108 Snapshot~ 50; +#X obj 442 108 Snapshot~ 50; +#X obj 25 144 Snapshot~ 50; +#X floatatom 26 340 10 0 0 0 - - -; +#X floatatom 26 236 10 0 0 0 - - -; +#X floatatom 152 236 5 0 0 0 - - -; +#X obj 26 304 Snapshot~ 50; +#X obj 26 267 log~; +#X obj 183 108 >~ 10000; +#X obj 183 144 edge~; +#X floatatom 234 342 10 0 0 0 - - -; +#X floatatom 234 238 10 0 0 0 - - -; +#X floatatom 360 238 5 0 0 0 - - -; +#X obj 234 306 Snapshot~ 50; +#X obj 234 269 pow~; +#X floatatom 439 341 10 0 0 0 - - -; +#X floatatom 439 237 10 0 0 0 - - -; +#X floatatom 565 237 5 0 0 0 - - -; +#X obj 439 305 Snapshot~ 50; +#X obj 439 268 atan2~; +#X connect 0 0 16 0; +#X connect 2 0 4 0; +#X connect 3 0 0 1; +#X connect 4 0 0 0; +#X connect 5 0 6 0; +#X connect 6 0 14 0; +#X connect 6 0 22 0; +#X connect 8 0 6 0; +#X connect 9 0 6 0; +#X connect 11 0 13 0; +#X connect 12 0 13 1; +#X connect 13 0 15 0; +#X connect 14 0 7 0; +#X connect 15 0 10 0; +#X connect 16 0 1 0; +#X connect 18 0 21 0; +#X connect 19 0 21 1; +#X connect 20 0 17 0; +#X connect 21 0 20 0; +#X connect 22 0 23 0; +#X connect 23 0 6 0; +#X connect 25 0 28 0; +#X connect 26 0 28 1; +#X connect 27 0 24 0; +#X connect 28 0 27 0; +#X connect 30 0 33 0; +#X connect 31 0 33 1; +#X connect 32 0 29 0; +#X connect 33 0 32 0; diff --git a/test/cyclone/sigsmoothers-test.pd b/test/cyclone/sigsmoothers-test.pd new file mode 100644 index 0000000..803d950 --- /dev/null +++ b/test/cyclone/sigsmoothers-test.pd @@ -0,0 +1,34 @@ +#N canvas 304 91 587 409 12; +#X obj 51 371 cyclone; +#X obj 51 340 sprintf import ../../../ref/c74help/text/%s.help; +#X msg 62 281 slide~; +#X msg 51 253 deltaclip~; +#X msg 72 309 rampsmooth~; +#X msg 114 48 1; +#X msg 65 48 0; +#X floatatom 65 79 0 0 0 0 - - -; +#X msg 165 85 ramp \$1; +#X floatatom 165 48 0 0 0 0 - - -; +#X obj 27 149 capture~ f; +#X msg 95 17 clear; +#X msg 27 17 clear; +#X obj 65 117 rampsmooth~; +#X obj 244 148 Scope~ 130 130 256 3 128 0 1 0 0 0 0 102 255 51 135 +135 135 0; +#X msg 244 117 range 0 1; +#X connect 1 0 0 0; +#X connect 2 0 1 0; +#X connect 3 0 1 0; +#X connect 4 0 1 0; +#X connect 5 0 7 0; +#X connect 6 0 7 0; +#X connect 7 0 13 0; +#X connect 8 0 13 0; +#X connect 9 0 8 0; +#X connect 11 0 10 0; +#X connect 11 0 5 0; +#X connect 12 0 6 0; +#X connect 12 0 10 0; +#X connect 13 0 10 0; +#X connect 13 0 14 0; +#X connect 15 0 14 0; diff --git a/test/cyclone/sigtrig-test.pd b/test/cyclone/sigtrig-test.pd new file mode 100644 index 0000000..01d88e5 --- /dev/null +++ b/test/cyclone/sigtrig-test.pd @@ -0,0 +1,80 @@ +#N canvas 210 153 573 323 12; +#N canvas 0 0 749 559 coords 0; +#X obj 199 114 cartopol~; +#X floatatom 199 21 5 0 0 0 - - -; +#X floatatom 275 58 5 0 0 0 - - -; +#X floatatom 199 287 0 0 0 0 - - -; +#X floatatom 275 205 0 0 0 0 - - -; +#X obj 199 257 snapshot~; +#X obj 275 175 snapshot~; +#X obj 66 114 metro 50; +#X obj 66 84 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 66 458 0 0 0 0 - - -; +#X floatatom 142 376 0 0 0 0 - - -; +#X obj 66 428 snapshot~; +#X obj 66 286 poltocar~; +#X obj 142 346 snapshot~; +#X floatatom 571 21 5 0 0 0 - - -; +#X floatatom 647 58 5 0 0 0 - - -; +#X floatatom 571 287 0 0 0 0 - - -; +#X floatatom 647 205 0 0 0 0 - - -; +#X obj 571 257 snapshot~; +#X obj 647 175 snapshot~; +#X obj 438 114 metro 50; +#X obj 438 84 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X floatatom 438 458 0 0 0 0 - - -; +#X floatatom 514 376 0 0 0 0 - - -; +#X obj 438 428 snapshot~; +#X obj 514 346 snapshot~; +#X obj 571 114 poltocar~; +#X obj 438 286 cartopol~; +#X obj 346 21 loadbang; +#X connect 0 0 5 0; +#X connect 0 0 12 0; +#X connect 0 1 6 0; +#X connect 0 1 12 1; +#X connect 1 0 0 0; +#X connect 2 0 0 1; +#X connect 5 0 3 0; +#X connect 6 0 4 0; +#X connect 7 0 6 0; +#X connect 7 0 5 0; +#X connect 7 0 13 0; +#X connect 7 0 11 0; +#X connect 8 0 7 0; +#X connect 11 0 9 0; +#X connect 12 0 11 0; +#X connect 12 1 13 0; +#X connect 13 0 10 0; +#X connect 14 0 26 0; +#X connect 15 0 26 1; +#X connect 18 0 16 0; +#X connect 19 0 17 0; +#X connect 20 0 19 0; +#X connect 20 0 18 0; +#X connect 20 0 25 0; +#X connect 20 0 24 0; +#X connect 21 0 20 0; +#X connect 24 0 22 0; +#X connect 25 0 23 0; +#X connect 26 0 18 0; +#X connect 26 0 27 0; +#X connect 26 1 19 0; +#X connect 26 1 27 1; +#X connect 27 0 24 0; +#X connect 27 1 25 0; +#X connect 28 0 8 0; +#X connect 28 0 21 0; +#X restore 42 41 pd coords; +#N canvas 135 57 659 466 -lm 0; +#X obj 31 70 acos~; +#X obj 30 120 Scope~ 229 132 256 3 128 0 3.15 0 0 0 0 102 255 51 135 +135 135 0; +#X msg 122 70 range 0 3.15; +#X obj 31 25 cycle~ 1; +#X connect 0 0 1 0; +#X connect 2 0 1 0; +#X connect 3 0 0 0; +#X restore 177 41 pd -lm; diff --git a/test/cyclone/sigwrappers-speed.pd b/test/cyclone/sigwrappers-speed.pd new file mode 100644 index 0000000..f680971 --- /dev/null +++ b/test/cyclone/sigwrappers-speed.pd @@ -0,0 +1,101 @@ +#N canvas 220 91 570 539 12; +#X obj 65 200 phasewrap~; +#X msg 20 19 0; +#X msg 71 19 1; +#X msg 122 19 2; +#X floatatom 71 53 5 0 0 0 - - -; +#X obj 168 200 phasewrap~; +#X obj 272 200 phasewrap~; +#X obj 376 200 phasewrap~; +#X obj 71 229 phasewrap~; +#X obj 174 229 phasewrap~; +#X obj 278 229 phasewrap~; +#X obj 382 229 phasewrap~; +#X obj 71 261 phasewrap~; +#X obj 174 261 phasewrap~; +#X obj 278 261 phasewrap~; +#X obj 382 261 phasewrap~; +#X obj 77 291 phasewrap~; +#X obj 180 291 phasewrap~; +#X obj 284 291 phasewrap~; +#X obj 388 291 phasewrap~; +#X obj 83 323 phasewrap~; +#X obj 186 323 phasewrap~; +#X obj 290 323 phasewrap~; +#X obj 394 323 phasewrap~; +#X obj 59 354 phasewrap~; +#X obj 162 354 phasewrap~; +#X obj 266 354 phasewrap~; +#X obj 370 354 phasewrap~; +#X obj 65 383 phasewrap~; +#X obj 168 383 phasewrap~; +#X obj 272 383 phasewrap~; +#X obj 376 383 phasewrap~; +#X obj 65 415 phasewrap~; +#X obj 168 415 phasewrap~; +#X obj 272 415 phasewrap~; +#X obj 376 415 phasewrap~; +#X obj 71 445 phasewrap~; +#X obj 174 445 phasewrap~; +#X obj 278 445 phasewrap~; +#X obj 382 445 phasewrap~; +#X obj 77 477 phasewrap~; +#X obj 180 477 phasewrap~; +#X obj 284 477 phasewrap~; +#X obj 388 477 phasewrap~; +#X msg 197 124 \$2 \, _algo \$1 \; pd dsp 0 \; pd dsp 1; +#X obj 197 92 pack; +#X floatatom 237 19 5 0 0 0 - - -; +#X obj 164 19 inlet; +#X obj 305 19 inlet; +#X obj 197 58 bondo; +#X connect 1 0 4 0; +#X connect 2 0 4 0; +#X connect 3 0 4 0; +#X connect 4 0 49 0; +#X connect 44 0 0 0; +#X connect 44 0 5 0; +#X connect 44 0 6 0; +#X connect 44 0 7 0; +#X connect 44 0 8 0; +#X connect 44 0 9 0; +#X connect 44 0 10 0; +#X connect 44 0 11 0; +#X connect 44 0 12 0; +#X connect 44 0 14 0; +#X connect 44 0 13 0; +#X connect 44 0 15 0; +#X connect 44 0 16 0; +#X connect 44 0 17 0; +#X connect 44 0 18 0; +#X connect 44 0 19 0; +#X connect 44 0 20 0; +#X connect 44 0 21 0; +#X connect 44 0 22 0; +#X connect 44 0 23 0; +#X connect 44 0 24 0; +#X connect 44 0 25 0; +#X connect 44 0 26 0; +#X connect 44 0 27 0; +#X connect 44 0 28 0; +#X connect 44 0 29 0; +#X connect 44 0 30 0; +#X connect 44 0 31 0; +#X connect 44 0 32 0; +#X connect 44 0 33 0; +#X connect 44 0 34 0; +#X connect 44 0 35 0; +#X connect 44 0 36 0; +#X connect 44 0 37 0; +#X connect 44 0 38 0; +#X connect 44 0 39 0; +#X connect 44 0 40 0; +#X connect 44 0 41 0; +#X connect 44 0 42 0; +#X connect 44 0 43 0; +#X connect 45 0 44 0; +#X connect 46 0 49 1; +#X connect 47 0 4 0; +#X connect 48 0 46 0; +#X connect 49 0 45 0; +#X connect 49 1 45 1; diff --git a/test/cyclone/sigwrappers-speed20.pd b/test/cyclone/sigwrappers-speed20.pd new file mode 100644 index 0000000..98143ec --- /dev/null +++ b/test/cyclone/sigwrappers-speed20.pd @@ -0,0 +1,63 @@ +#N canvas 441 249 467 396 12; +#X obj 46 77 sigwrappers-speed; +#X floatatom 123 29 5 0 0 0 - - -; +#X floatatom 293 29 5 0 0 0 - - -; +#X obj 46 107 sigwrappers-speed; +#X obj 46 137 sigwrappers-speed; +#X obj 46 167 sigwrappers-speed; +#X obj 46 197 sigwrappers-speed; +#X obj 46 227 sigwrappers-speed; +#X obj 46 257 sigwrappers-speed; +#X obj 228 77 sigwrappers-speed; +#X obj 228 107 sigwrappers-speed; +#X obj 228 137 sigwrappers-speed; +#X obj 228 167 sigwrappers-speed; +#X obj 228 197 sigwrappers-speed; +#X obj 228 227 sigwrappers-speed; +#X obj 228 257 sigwrappers-speed; +#X obj 46 287 sigwrappers-speed; +#X obj 46 317 sigwrappers-speed; +#X obj 46 347 sigwrappers-speed; +#X obj 228 287 sigwrappers-speed; +#X obj 228 317 sigwrappers-speed; +#X obj 228 347 sigwrappers-speed; +#X connect 1 0 0 0; +#X connect 1 0 3 0; +#X connect 1 0 4 0; +#X connect 1 0 5 0; +#X connect 1 0 6 0; +#X connect 1 0 7 0; +#X connect 1 0 8 0; +#X connect 1 0 9 0; +#X connect 1 0 10 0; +#X connect 1 0 11 0; +#X connect 1 0 12 0; +#X connect 1 0 13 0; +#X connect 1 0 14 0; +#X connect 1 0 15 0; +#X connect 1 0 16 0; +#X connect 1 0 17 0; +#X connect 1 0 18 0; +#X connect 1 0 19 0; +#X connect 1 0 20 0; +#X connect 1 0 21 0; +#X connect 2 0 0 1; +#X connect 2 0 3 1; +#X connect 2 0 4 1; +#X connect 2 0 5 1; +#X connect 2 0 6 1; +#X connect 2 0 7 1; +#X connect 2 0 8 1; +#X connect 2 0 16 1; +#X connect 2 0 17 1; +#X connect 2 0 18 1; +#X connect 2 0 9 1; +#X connect 2 0 10 1; +#X connect 2 0 11 1; +#X connect 2 0 12 1; +#X connect 2 0 13 1; +#X connect 2 0 14 1; +#X connect 2 0 15 1; +#X connect 2 0 19 1; +#X connect 2 0 20 1; +#X connect 2 0 21 1; diff --git a/test/cyclone/sigwrappers-test.pd b/test/cyclone/sigwrappers-test.pd new file mode 100644 index 0000000..c675fb4 --- /dev/null +++ b/test/cyclone/sigwrappers-test.pd @@ -0,0 +1,34 @@ +#N canvas 468 231 530 478 12; +#X obj 38 200 phasewrap~; +#X floatatom 234 68 0 0 0 0 - - -; +#X obj 175 200 _phasewrap1~; +#X obj 336 200 _phasewrap2~; +#X obj 234 102 * 0.01; +#X floatatom 38 273 0 0 0 0 - - -; +#X floatatom 175 273 0 0 0 0 - - -; +#X floatatom 336 273 0 0 0 0 - - -; +#X floatatom 175 154 0 0 0 0 - - -; +#X floatatom 49 68 5 0 0 0 - - -; +#X obj 129 102 acos; +#X obj 107 135 *; +#X msg 129 68 -1; +#X obj 129 33 loadbang; +#X obj 38 237 Snapshot~ 20; +#X obj 175 237 Snapshot~ 20; +#X obj 336 237 Snapshot~ 20; +#X connect 0 0 14 0; +#X connect 1 0 4 0; +#X connect 2 0 15 0; +#X connect 3 0 16 0; +#X connect 4 0 8 0; +#X connect 8 0 0 0; +#X connect 8 0 2 0; +#X connect 8 0 3 0; +#X connect 9 0 11 0; +#X connect 10 0 11 1; +#X connect 11 0 8 0; +#X connect 12 0 10 0; +#X connect 13 0 12 0; +#X connect 14 0 5 0; +#X connect 15 0 6 0; +#X connect 16 0 7 0; diff --git a/test/cyclone/spectrum-pm.pd b/test/cyclone/spectrum-pm.pd new file mode 100644 index 0000000..db35ca8 --- /dev/null +++ b/test/cyclone/spectrum-pm.pd @@ -0,0 +1,34 @@ +#N canvas 189 215 712 594 12; +#X obj 62 350 Scope~ 562 220 2 3 512 0 512 0 0 0 0 102 255 51 135 135 +135 0; +#X obj 174 234 cartopol~; +#X obj 174 190 rfft~; +#X obj 23 25 block~ 1024; +#X obj 62 276 vectral~ 1024; +#X obj 62 142 count~ 0 1024 1 1; +#X floatatom 284 100 5 0 0 0 - - -; +#X floatatom 378 25 5 0 0 0 - - -; +#X floatatom 111 190 5 0 0 0 - - -; +#X obj 378 100 *~ 1; +#X floatatom 440 100 5 0 0 0 - - -; +#X obj 62 234 *~ 0.3; +#X obj 284 142 cycle~ 3000; +#X obj 378 62 cycle~ 1000; +#X msg 210 276 slide 10 10; +#X msg 130 310 range 0 512 \, 2 \, bufsize 512; +#X connect 1 0 4 2; +#X connect 2 0 1 0; +#X connect 2 1 1 1; +#X connect 4 0 0 0; +#X connect 5 0 4 1; +#X connect 5 0 11 0; +#X connect 6 0 12 0; +#X connect 7 0 13 0; +#X connect 8 0 11 1; +#X connect 9 0 12 1; +#X connect 10 0 9 1; +#X connect 11 0 4 0; +#X connect 12 0 2 0; +#X connect 13 0 9 0; +#X connect 14 0 4 0; +#X connect 15 0 0 0; diff --git a/test/cyclone/speedlim-test.pd b/test/cyclone/speedlim-test.pd new file mode 100644 index 0000000..04b6edf --- /dev/null +++ b/test/cyclone/speedlim-test.pd @@ -0,0 +1,63 @@ +#N canvas 385 195 511 382 12; +#X obj 191 306 speedlim; +#X msg 191 31 bang; +#X obj 191 331 print; +#X msg 258 266 0; +#X msg 301 266 10; +#X msg 342 266 500; +#X msg 263 66 1; +#X msg 306 66 2; +#X msg 349 66 3; +#X msg 393 66 4; +#X obj 279 92 pipe 490; +#X obj 279 117 pipe 510; +#X obj 279 142 pipe 990; +#X obj 279 167 pipe 1600; +#X obj 279 192 pipe 2010; +#X obj 279 217 pipe 2020; +#X msg 393 91 5; +#X msg 393 116 6; +#X msg 393 141 7; +#X msg 263 31 bang; +#X msg 384 266 3000; +#X msg 106 235 one; +#X msg 80 203 symbol two; +#X msg 55 175 perhaps three; +#X obj 30 143 testmess 300; +#X msg 30 66 test; +#X obj 30 104 t a b b b; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 0 1; +#X connect 4 0 0 1; +#X connect 5 0 0 1; +#X connect 6 0 0 0; +#X connect 7 0 10 0; +#X connect 8 0 11 0; +#X connect 9 0 12 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 15 0 0 0; +#X connect 16 0 13 0; +#X connect 17 0 14 0; +#X connect 18 0 15 0; +#X connect 19 0 6 0; +#X connect 19 0 7 0; +#X connect 19 0 8 0; +#X connect 19 0 9 0; +#X connect 19 0 16 0; +#X connect 19 0 17 0; +#X connect 19 0 18 0; +#X connect 20 0 0 1; +#X connect 21 0 0 0; +#X connect 22 0 0 0; +#X connect 23 0 0 0; +#X connect 24 0 0 0; +#X connect 25 0 26 0; +#X connect 26 0 24 0; +#X connect 26 1 23 0; +#X connect 26 2 22 0; +#X connect 26 3 21 0; diff --git a/test/cyclone/spell-test.pd b/test/cyclone/spell-test.pd new file mode 100644 index 0000000..dd56e0c --- /dev/null +++ b/test/cyclone/spell-test.pd @@ -0,0 +1,26 @@ +#N canvas 469 262 450 300 12; +#X obj 130 233 spell 7 -0.5; +#X msg 311 140 symbol test; +#X obj 130 261 print; +#X msg 311 168 another test; +#X msg 40 191 bang; +#X msg 130 106 99; +#X msg 177 106 99.99; +#X msg 79 106 -99; +#X msg 243 106 1 2 3; +#X msg 311 106 1 2.5 3; +#X msg 311 78 1 test 3; +#X obj 35 58 sprintf %c; +#X msg 35 30 129; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 0 0; +#X connect 9 0 0 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 11 0; diff --git a/test/cyclone/spike-test.pd b/test/cyclone/spike-test.pd new file mode 100644 index 0000000..4fb168c --- /dev/null +++ b/test/cyclone/spike-test.pd @@ -0,0 +1,23 @@ +#N canvas 442 260 450 300 12; +#X obj 59 186 spike~; +#X obj 59 225 print; +#X obj 59 75 phasor~ 1; +#X floatatom 59 38 5 0 0 0 - - -; +#X floatatom 131 149 5 0 0 0 - - -; +#X floatatom 133 225 10 0 0 0 - - -; +#X obj 59 112 change~; +#X obj 59 149 +~ 1; +#X obj 239 186 spike~; +#X floatatom 311 149 5 0 0 0 - - -; +#X floatatom 313 225 10 0 0 0 - - -; +#X obj 239 149 -~ 1; +#X connect 0 0 5 0; +#X connect 2 0 6 0; +#X connect 3 0 2 0; +#X connect 4 0 0 1; +#X connect 6 0 7 0; +#X connect 6 0 11 0; +#X connect 7 0 0 0; +#X connect 8 0 10 0; +#X connect 9 0 8 1; +#X connect 11 0 8 0; diff --git a/test/cyclone/split-test.pd b/test/cyclone/split-test.pd new file mode 100644 index 0000000..860faa8 --- /dev/null +++ b/test/cyclone/split-test.pd @@ -0,0 +1,48 @@ +#N canvas 300 45 610 348 12; +#X obj 176 212 split; +#X msg 99 95 1.5 1 2; +#X floatatom 176 252 5 0 0; +#X floatatom 279 252 5 0 0; +#X obj 176 295 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 279 295 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 176 36 5 0 0; +#X floatatom 196 68 5 0 0; +#X floatatom 216 101 5 0 0; +#X msg 313 89 test; +#X msg 313 121 list test; +#X msg 313 57 1.5 test; +#X msg 36 68 1.5 1.5 2; +#X msg 36 142 2.5 1.5 2.4; +#X floatatom 433 222 5 0 0; +#X floatatom 536 222 5 0 0; +#X obj 433 265 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 536 265 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 433 142 5 0 0; +#X obj 433 101 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X msg 313 153 3.5; +#X obj 433 182 split 3.5; +#X connect 0 0 2 0; +#X connect 0 1 3 0; +#X connect 1 0 0 0; +#X connect 2 0 4 0; +#X connect 3 0 5 0; +#X connect 6 0 0 0; +#X connect 7 0 0 1; +#X connect 8 0 0 2; +#X connect 9 0 0 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 13 0 0 0; +#X connect 14 0 16 0; +#X connect 15 0 17 0; +#X connect 18 0 21 0; +#X connect 19 0 18 0; +#X connect 20 0 0 1; +#X connect 21 0 14 0; +#X connect 21 1 15 0; diff --git a/test/cyclone/spray-test.pd b/test/cyclone/spray-test.pd new file mode 100644 index 0000000..5c2cbd1 --- /dev/null +++ b/test/cyclone/spray-test.pd @@ -0,0 +1,82 @@ +#N canvas 210 202 708 466 12; +#X obj 75 243 spray; +#X obj 75 324 print a; +#X obj 115 284 print b; +#X obj 221 332 spray 5; +#X obj 235 374 print; +#X obj 221 405 print first; +#X obj 465 370 print; +#X obj 451 401 print first; +#X obj 451 328 spray 5 -3; +#X msg 451 110 \$1 1 2 3 4 5; +#X msg 470 136 \$1 1 2 3 4; +#X msg 484 163 \$1 1 2 3; +#X msg 497 190 \$1 1 2; +#X msg 504 216 \$1 1; +#X msg 513 240 \$1 test 2 3 4 5; +#X msg 517 269 \$1 1 test 3 4 5; +#X msg 221 114 \$1 1 2 3 4 5; +#X msg 240 141 \$1 1 2 3 4; +#X msg 254 167 \$1 1 2 3; +#X msg 266 194 \$1 1 2; +#X msg 274 220 \$1 1; +#X msg 283 244 \$1 test 2 3 4 5; +#X msg 287 273 \$1 1 test 3 4 5; +#X msg 75 110 \$1 1 2 3 4 5; +#X msg 94 136 \$1 1 2 3 4; +#X msg 108 163 \$1 1 2 3; +#X msg 120 190 \$1 1 2; +#X msg 128 216 \$1 1; +#X floatatom 130 61 5 0 0; +#X floatatom 250 62 5 0 0; +#X floatatom 487 58 5 0 0; +#X connect 0 0 1 0; +#X connect 0 1 2 0; +#X connect 3 0 5 0; +#X connect 3 1 4 0; +#X connect 3 2 4 0; +#X connect 3 3 4 0; +#X connect 3 4 4 0; +#X connect 8 0 7 0; +#X connect 8 1 6 0; +#X connect 8 2 6 0; +#X connect 8 3 6 0; +#X connect 8 4 6 0; +#X connect 9 0 8 0; +#X connect 10 0 8 0; +#X connect 11 0 8 0; +#X connect 12 0 8 0; +#X connect 13 0 8 0; +#X connect 14 0 8 0; +#X connect 15 0 8 0; +#X connect 16 0 3 0; +#X connect 17 0 3 0; +#X connect 18 0 3 0; +#X connect 19 0 3 0; +#X connect 20 0 3 0; +#X connect 21 0 3 0; +#X connect 22 0 3 0; +#X connect 23 0 0 0; +#X connect 24 0 0 0; +#X connect 25 0 0 0; +#X connect 26 0 0 0; +#X connect 27 0 0 0; +#X connect 28 0 23 0; +#X connect 28 0 24 0; +#X connect 28 0 25 0; +#X connect 28 0 26 0; +#X connect 28 0 27 0; +#X connect 29 0 16 0; +#X connect 29 0 17 0; +#X connect 29 0 18 0; +#X connect 29 0 19 0; +#X connect 29 0 20 0; +#X connect 29 0 21 0; +#X connect 29 0 22 0; +#X connect 30 0 9 0; +#X connect 30 0 10 0; +#X connect 30 0 11 0; +#X connect 30 0 12 0; +#X connect 30 0 13 0; +#X connect 30 0 14 0; +#X connect 30 0 15 0; diff --git a/test/cyclone/substitute-test.pd b/test/cyclone/substitute-test.pd new file mode 100644 index 0000000..37e1a95 --- /dev/null +++ b/test/cyclone/substitute-test.pd @@ -0,0 +1,56 @@ +#N canvas 179 48 593 501 12; +#X obj 281 458 substitute; +#X msg 281 418 1 2 3; +#X obj 180 342 print replaced; +#X obj 398 347 print unchanged; +#X obj 180 314 substitute foo bar; +#X msg 28 73 bang; +#X msg 61 102 set bang; +#X msg 180 30 hello foo boo; +#X msg 147 102 set bang; +#X msg 252 102 one; +#X msg 148 149 foo 34; +#X msg 253 137 1 2 3 4; +#X msg 302 102 one two three; +#X msg 334 137 1 2 foo 4; +#X msg 438 102 foo foo foo 77; +#X msg 337 172 foo fum; +#X msg 427 172 1 otherhit; +#X msg 427 200 set 1 hithere; +#X msg 428 236 set; +#X msg 218 73 bang; +#X msg 39 259 symbol sym; +#X msg 428 264 symbol test; +#X msg 255 381 bang; +#X msg 341 381 bang; +#X msg 256 172 1; +#X msg 366 418 1 2; +#X msg 426 418 2 3; +#X connect 0 0 2 0; +#X connect 0 0 26 0; +#X connect 0 1 3 0; +#X connect 1 0 0 0; +#X connect 4 0 2 0; +#X connect 4 1 3 0; +#X connect 5 0 4 0; +#X connect 6 0 4 0; +#X connect 7 0 4 0; +#X connect 8 0 4 1; +#X connect 9 0 4 0; +#X connect 10 0 4 0; +#X connect 11 0 4 0; +#X connect 12 0 4 1; +#X connect 13 0 4 0; +#X connect 14 0 4 0; +#X connect 15 0 4 1; +#X connect 16 0 4 1; +#X connect 17 0 4 1; +#X connect 18 0 4 1; +#X connect 19 0 4 1; +#X connect 20 0 4 0; +#X connect 21 0 4 1; +#X connect 22 0 0 0; +#X connect 23 0 0 1; +#X connect 24 0 4 0; +#X connect 25 0 0 1; +#X connect 26 0 0 1; diff --git a/test/cyclone/switch-test.pd b/test/cyclone/switch-test.pd new file mode 100644 index 0000000..ec7fe2f --- /dev/null +++ b/test/cyclone/switch-test.pd @@ -0,0 +1,35 @@ +#N canvas 333 279 593 442 12; +#X obj 123 227 switch 11 1 padding; +#X msg 138 50 bang; +#X msg 153 87 2; +#X msg 168 122 symbol three; +#X msg 183 155 1 2 3 4; +#X msg 198 190 five is anything; +#X msg 72 155 bang; +#X obj 72 190 grab; +#X floatatom 72 318 5 0 0; +#X floatatom 68 50 5 0 0; +#X obj 167 282 route bang float symbol list; +#X obj 167 322 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X floatatom 228 318 5 0 0; +#X symbolatom 290 318 10 0 0; +#X obj 352 355 print list; +#X obj 414 318 print anything; +#X msg 289 50 last is anything too; +#X connect 0 0 10 0; +#X connect 1 0 0 1; +#X connect 2 0 0 2; +#X connect 3 0 0 3; +#X connect 4 0 0 4; +#X connect 5 0 0 5; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 7 1 0 0; +#X connect 9 0 0 0; +#X connect 10 0 11 0; +#X connect 10 1 12 0; +#X connect 10 2 13 0; +#X connect 10 3 14 0; +#X connect 10 4 15 0; +#X connect 16 0 0 11; diff --git a/test/cyclone/test.capture b/test/cyclone/test.capture new file mode 100644 index 0000000..238343a --- /dev/null +++ b/test/cyclone/test.capture @@ -0,0 +1,2 @@ +ffffffff fffffffe fffffffd fffffffc fffffffb fffffffa fffffff9 fffffff8 fffffff7 +fffffff6 diff --git a/test/cyclone/test.funbuff b/test/cyclone/test.funbuff new file mode 100644 index 0000000..2c89038 --- /dev/null +++ b/test/cyclone/test.funbuff @@ -0,0 +1,10 @@ +funbuff 0 -0 1 -1 2 -2 3 -3 4 -4 5 -5 6 -6 7 -7 8 -8 9 -9 10 -10 11 +-11 12 -12 13 -13 14 -14 15 -15 16 -16 17 -17 18 -18 19 -19 20 -20 +21 -21 22 -22 23 -23 24 -24 25 -25 26 -26 27 -27 28 -28 29 -29 30 -30 +31 -31 32 -32 33 -33 34 -34 35 -35 36 -36 37 -37 38 -38 39 -39 40 -40 +41 -41 42 -42 43 -43 44 -44 45 -45 46 -46 47 -47 48 -48 49 -49 50 -50 +51 -51 52 -52 53 -53 54 -54 55 -55 56 -56 57 -57 58 -58 59 -59 60 -60 +61 -61 62 -62 63 -63 64 -64 65 -65 66 -66 67 -67 68 -68 69 -69 70 -70 +71 -71 72 -72 73 -73 74 -74 75 -75 76 -76 77 -77 78 -78 79 -79 80 -80 +81 -81 82 -82 83 -83 84 -84 85 -85 86 -86 87 -87 88 -88 89 -89 90 -90 +91 -91 92 -92 93 -93 94 -94 95 -95 96 -96 97 -97 98 -98 99 -99
\ No newline at end of file diff --git a/test/cyclone/test.mid b/test/cyclone/test.mid Binary files differnew file mode 100644 index 0000000..9547e79 --- /dev/null +++ b/test/cyclone/test.mid diff --git a/test/cyclone/test.pool b/test/cyclone/test.pool new file mode 100644 index 0000000..22c43be --- /dev/null +++ b/test/cyclone/test.pool @@ -0,0 +1,2 @@ +sample /mnt/win_d/III_rok/Janek/krotkie/niskie_smyki.wav +sample /mnt/win_d/III_rok/Janek/krotkie/wysokie_smyki.wav diff --git a/test/cyclone/test.seq b/test/cyclone/test.seq new file mode 100644 index 0000000..88b1657 --- /dev/null +++ b/test/cyclone/test.seq @@ -0,0 +1,1208 @@ +0 193 107; +10 145 71 79; +455 145 73 88; +475 129 71 0; +739 145 74 88; +748 129 73 0; +1138 145 76 94; +1154 129 74 0; +1255 145 74 92; +1270 129 76 0; +1486 145 73 79; +1508 129 74 0; +1574 145 74 80; +1589 129 73 0; +1660 145 73 79; +1673 129 74 0; +1762 145 69 80; +1784 129 73 0; +1984 145 66 76; +2002 129 69 0; +2231 145 71 79; +2257 129 66 0; +2496 145 64 88; +2525 129 71 0; +2739 145 66 76; +2763 129 64 0; +2976 145 67 80; +2985 129 66 0; +3108 129 67 0; +3243 145 67 76; +3381 129 67 0; +3494 145 67 77; +3694 129 67 0; +3734 145 66 69; +3994 145 71 80; +4004 129 66 0; +4242 145 59 79; +4256 129 71 0; +4483 194 98; +4493 146 76 79; +4494 145 60 80; +4509 129 59 0; +4611 145 59 79; +4635 129 60 0; +4727 145 60 80; +4746 129 59 0; +4846 145 57 79; +4868 129 60 0; +4934 146 78 88; +4954 130 76 0; +4961 145 62 80; +4981 129 57 0; +5074 145 59 80; +5085 129 62 0; +5204 145 64 80; +5214 146 79 88; +5219 129 59 0; +5222 130 78 0; +5612 146 81 94; +5628 130 79 0; +5650 129 64 0; +5729 146 79 92; +5735 145 64 88; +5744 130 81 0; +5943 129 64 0; +5959 146 78 79; +5981 145 62 88; +5981 130 79 0; +6047 146 79 80; +6062 130 78 0; +6133 146 78 79; +6146 130 79 0; +6235 146 74 80; +6257 130 78 0; +6345 145 59 80; +6373 129 62 0; +6456 146 71 76; +6462 145 55 88; +6465 129 59 0; +6472 130 74 0; +6570 145 54 80; +6592 129 55 0; +6700 146 76 79; +6702 145 52 88; +6716 129 54 0; +6725 130 71 0; +6825 145 50 88; +6847 129 52 0; +6955 145 48 80; +6964 146 69 88; +6967 129 50 0; +6993 130 76 0; +7207 146 71 76; +7231 130 69 0; +7444 146 72 80; +7453 130 71 0; +7462 145 53 88; +7485 129 48 0; +7576 130 72 0; +7711 146 72 76; +7849 130 72 0; +7957 145 52 92; +7962 146 72 77; +7978 129 53 0; +8161 130 72 0; +8170 129 52 0; +8201 146 71 69; +8220 145 52 88; +8460 146 76 80; +8470 130 71 0; +8580 145 50 80; +8593 129 52 0; +8701 145 48 88; +8707 146 64 79; +8712 129 50 0; +8721 130 76 0; +8819 145 50 79; +8829 129 48 0; +8946 145 38 80; +8947 195 74; +8957 147 81 79; +8958 146 65 80; +8963 129 50 0; +8973 130 64 0; +9075 146 64 79; +9099 130 65 0; +9191 146 65 80; +9210 130 64 0; +9303 145 41 80; +9309 146 62 79; +9319 129 38 0; +9330 130 65 0; +9396 147 83 88; +9416 131 81 0; +9423 146 67 80; +9425 145 40 80; +9428 129 41 0; +9442 130 62 0; +9535 146 64 80; +9546 130 67 0; +9665 146 69 80; +9675 147 84 88; +9680 130 64 0; +9681 145 45 80; +9683 131 83 0; +9702 129 40 0; +10026 129 45 0; +10057 145 45 88; +10072 147 86 94; +10088 131 84 0; +10110 130 69 0; +10138 129 45 0; +10169 145 45 80; +10188 147 84 92; +10194 146 69 88; +10203 131 86 0; +10283 145 48 84; +10293 129 45 0; +10401 130 69 0; +10417 147 83 79; +10420 145 47 88; +10436 129 48 0; +10437 146 67 88; +10437 131 84 0; +10503 147 84 80; +10518 131 83 0; +10589 147 83 79; +10602 131 84 0; +10680 145 40 80; +10689 129 47 0; +10691 147 79 80; +10713 131 83 0; +10801 146 64 80; +10829 130 67 0; +10912 147 76 76; +10918 146 60 88; +10921 130 64 0; +10928 131 79 0; +11026 146 59 80; +11048 130 60 0; +11156 147 81 79; +11158 146 57 88; +11163 145 38 88; +11172 130 59 0; +11174 129 40 0; +11180 131 76 0; +11280 146 55 88; +11302 130 57 0; +11410 146 53 80; +11419 147 74 88; +11422 130 55 0; +11448 131 81 0; +11662 145 36 80; +11662 147 76 76; +11673 129 38 0; +11686 131 74 0; +11899 147 77 80; +11908 131 76 0; +11917 145 34 76; +11917 146 58 88; +11940 130 53 0; +11945 129 36 0; +12030 131 77 0; +12032 145 36 79; +12045 129 34 0; +12164 145 38 88; +12164 147 77 76; +12188 129 36 0; +12301 131 77 0; +12409 146 57 92; +12414 147 77 77; +12430 130 58 0; +12613 131 77 0; +12622 130 57 0; +12653 147 76 69; +12660 145 36 78; +12671 146 57 88; +12678 129 38 0; +12782 145 35 80; +12804 129 36 0; +12900 129 35 0; +12900 145 33 72; +12910 147 81 80; +12920 131 76 0; +13030 146 55 80; +13043 130 57 0; +13151 146 53 88; +13157 147 69 79; +13160 145 45 88; +13161 130 55 0; +13170 131 81 0; +13183 129 33 0; +13268 146 55 79; +13278 130 53 0; +13395 146 43 80; +13396 196 38; +13406 148 74 79; +13407 145 43 88; +13407 147 70 80; +13412 130 55 0; +13422 131 69 0; +13424 129 45 0; +13524 147 69 79; +13548 131 70 0; +13640 147 70 80; +13659 131 69 0; +13752 146 46 80; +13758 147 67 79; +13763 145 46 80; +13768 130 43 0; +13779 131 70 0; +13780 129 43 0; +13845 148 76 88; +13865 132 74 0; +13872 147 72 80; +13874 146 45 80; +13877 130 46 0; +13886 145 45 84; +13891 131 67 0; +13893 129 46 0; +13984 147 69 80; +13995 131 72 0; +14114 147 74 80; +14124 148 77 88; +14129 131 69 0; +14130 146 50 80; +14132 132 76 0; +14134 145 50 94; +14150 129 45 0; +14150 130 45 0; +14472 129 50 0; +14473 130 50 0; +14497 145 50 80; +14503 146 50 88; +14518 148 79 94; +14534 132 77 0; +14556 131 74 0; +14580 129 50 0; +14583 130 50 0; +14607 145 50 79; +14613 146 50 80; +14632 148 77 92; +14638 147 74 88; +14647 132 79 0; +14727 146 53 84; +14729 145 53 84; +14736 130 50 0; +14741 129 50 0; +14843 131 74 0; +14859 148 76 79; +14860 145 52 92; +14862 146 52 88; +14878 130 53 0; +14879 147 72 88; +14879 132 77 0; +14880 129 53 0; +14945 148 77 80; +14960 132 76 0; +15031 148 76 79; +15044 132 77 0; +15115 145 45 88; +15117 129 52 0; +15120 146 45 80; +15129 130 52 0; +15131 148 72 80; +15153 132 76 0; +15241 147 69 80; +15269 131 72 0; +15352 148 69 76; +15358 147 65 88; +15361 131 69 0; +15368 132 72 0; +15466 147 64 80; +15488 131 65 0; +15596 148 74 79; +15598 147 62 88; +15603 146 43 88; +15605 145 43 88; +15611 131 64 0; +15613 130 45 0; +15615 129 45 0; +15618 132 69 0; +15718 147 60 88; +15740 131 62 0; +15848 147 58 80; +15857 148 67 88; +15860 131 60 0; +15886 132 74 0; +16100 146 41 80; +16100 148 69 76; +16111 145 41 92; +16111 130 43 0; +16124 132 67 0; +16129 129 43 0; +16337 148 70 80; +16346 132 69 0; +16347 145 39 80; +16354 146 39 76; +16354 147 63 88; +16365 129 41 0; +16376 131 58 0; +16381 130 41 0; +16465 145 41 92; +16466 132 70 0; +16468 146 41 79; +16481 129 39 0; +16481 130 39 0; +16589 145 43 80; +16600 146 43 88; +16600 148 70 76; +16606 129 41 0; +16624 130 41 0; +16737 132 70 0; +16835 145 41 88; +16844 147 62 92; +16849 148 70 77; +16862 129 43 0; +16865 131 63 0; +16956 145 40 88; +16976 129 41 0; +17047 132 70 0; +17056 131 62 0; +17087 148 69 69; +17088 145 38 80; +17094 146 41 78; +17097 129 40 0; +17104 147 62 88; +17111 130 43 0; +17215 146 40 80; +17237 130 41 0; +17333 130 40 0; +17333 146 38 72; +17343 148 74 80; +17353 132 69 0; +17463 147 60 80; +17476 131 62 0; +17569 129 38 0; +17583 147 58 88; +17589 148 62 79; +17592 146 50 88; +17593 131 60 0; +17602 132 74 0; +17615 130 38 0; +17700 147 60 79; +17710 131 58 0; +17827 147 48 80; +17828 193 44; +17838 145 67 79; +17839 146 48 88; +17839 148 63 80; +17844 131 60 0; +17854 132 62 0; +17856 130 50 0; +17956 148 62 79; +17980 132 63 0; +18072 148 63 80; +18091 132 62 0; +18184 147 51 80; +18190 148 60 79; +18195 146 51 80; +18200 131 48 0; +18211 132 63 0; +18212 130 48 0; +18277 145 69 88; +18297 129 67 0; +18304 148 65 80; +18306 147 50 80; +18309 131 51 0; +18318 146 50 84; +18323 132 60 0; +18325 130 51 0; +18416 148 62 80; +18427 132 65 0; +18546 148 67 80; +18556 145 70 88; +18561 132 62 0; +18562 147 55 80; +18564 129 69 0; +18566 146 55 94; +18582 130 50 0; +18582 131 50 0; +18904 130 55 0; +18905 131 55 0; +18929 146 55 80; +18935 147 55 88; +18950 145 72 94; +18966 129 70 0; +18988 132 67 0; +19012 130 55 0; +19015 131 55 0; +19039 146 55 79; +19045 147 55 80; +19064 145 70 92; +19070 148 67 88; +19079 129 72 0; +19159 147 58 84; +19161 146 58 84; +19168 131 55 0; +19173 130 55 0; +19275 132 67 0; +19291 145 69 79; +19292 146 57 92; +19294 147 57 88; +19310 131 58 0; +19311 129 70 0; +19311 148 65 88; +19312 130 58 0; +19377 145 70 80; +19392 129 69 0; +19463 145 69 79; +19476 129 70 0; +19547 146 50 88; +19549 130 57 0; +19552 147 50 80; +19561 131 57 0; +19563 145 65 80; +19585 129 69 0; +19673 148 62 80; +19701 132 65 0; +19784 145 62 76; +19790 148 58 88; +19793 132 62 0; +19800 129 65 0; +19898 148 57 80; +19920 132 58 0; +20028 145 67 79; +20030 148 55 88; +20035 147 48 88; +20037 146 48 88; +20043 132 57 0; +20045 131 50 0; +20047 130 50 0; +20050 129 62 0; +20150 148 53 88; +20172 132 55 0; +20280 148 51 80; +20289 145 60 88; +20292 132 53 0; +20318 129 67 0; +20532 145 62 76; +20532 147 46 80; +20543 146 46 92; +20543 131 48 0; +20556 129 60 0; +20561 130 48 0; +20769 145 63 80; +20778 129 62 0; +20779 146 44 80; +20786 147 44 76; +20786 148 56 88; +20797 130 46 0; +20808 132 51 0; +20813 131 46 0; +20897 146 46 92; +20898 129 63 0; +20900 147 46 79; +20913 130 44 0; +20913 131 44 0; +21021 146 48 80; +21032 145 63 76; +21032 147 48 88; +21038 130 46 0; +21056 131 46 0; +21169 129 63 0; +21267 146 46 88; +21276 148 55 92; +21281 145 63 77; +21294 130 48 0; +21297 132 56 0; +21388 146 45 88; +21408 130 46 0; +21479 129 63 0; +21488 132 55 0; +21519 145 62 69; +21520 146 43 80; +21526 147 46 78; +21529 130 45 0; +21536 148 55 88; +21543 131 48 0; +21647 147 45 80; +21669 131 46 0; +21765 131 45 0; +21765 147 43 72; +21775 145 67 80; +21785 129 62 0; +21895 148 53 80; +21908 132 55 0; +22001 130 43 0; +22015 148 51 88; +22021 145 55 79; +22024 147 55 88; +22025 132 53 0; +22034 129 67 0; +22047 131 43 0; +22132 148 53 79; +22142 132 51 0; +22259 148 41 80; +22260 194 66; +22270 146 72 79; +22271 145 56 80; +22271 147 53 88; +22276 132 53 0; +22286 129 55 0; +22288 131 55 0; +22388 145 55 79; +22412 129 56 0; +22504 145 56 80; +22523 129 55 0; +22616 148 44 80; +22622 145 53 79; +22627 147 56 80; +22632 132 41 0; +22643 129 56 0; +22644 131 53 0; +22709 146 74 88; +22729 130 72 0; +22736 145 58 80; +22738 148 43 80; +22741 132 44 0; +22750 147 55 84; +22755 129 53 0; +22757 131 56 0; +22848 145 55 80; +22859 129 58 0; +22978 145 60 80; +22988 146 75 88; +22993 129 55 0; +22994 148 48 80; +22996 130 74 0; +22998 147 60 94; +23014 131 55 0; +23014 132 43 0; +23336 131 60 0; +23337 132 48 0; +23361 147 60 80; +23367 148 48 88; +23382 146 77 94; +23398 130 75 0; +23420 129 60 0; +23444 131 60 0; +23447 132 48 0; +23471 147 60 79; +23477 148 48 80; +23496 146 75 92; +23502 145 60 88; +23511 130 77 0; +23591 148 51 84; +23593 147 63 84; +23600 132 48 0; +23605 131 60 0; +23707 129 60 0; +23723 146 74 79; +23724 147 62 92; +23726 148 50 88; +23742 132 51 0; +23743 145 58 88; +23743 130 75 0; +23744 131 63 0; +23809 146 75 80; +23824 130 74 0; +23895 146 74 79; +23908 130 75 0; +23979 147 55 88; +23981 131 62 0; +23984 148 43 80; +23993 132 50 0; +23995 146 70 80; +24017 130 74 0; +24105 145 55 80; +24133 129 58 0; +24216 146 67 76; +24222 145 51 88; +24225 129 55 0; +24232 130 70 0; +24330 145 50 80; +24352 129 51 0; +24460 146 72 79; +24462 145 48 88; +24467 148 41 88; +24469 147 53 88; +24475 129 50 0; +24477 132 43 0; +24479 131 55 0; +24482 130 67 0; +24582 145 46 88; +24604 129 48 0; +24712 145 44 80; +24721 146 65 88; +24724 129 46 0; +24750 130 72 0; +24964 146 67 76; +24964 148 39 80; +24975 147 51 92; +24975 132 41 0; +24988 130 65 0; +24993 131 53 0; +25201 146 68 80; +25210 130 67 0; +25211 147 49 80; +25218 145 49 88; +25218 148 37 76; +25229 131 51 0; +25240 129 44 0; +25245 132 39 0; +25329 147 51 92; +25330 130 68 0; +25332 148 39 79; +25345 131 49 0; +25345 132 37 0; +25453 147 53 80; +25464 146 68 76; +25464 148 41 88; +25470 131 51 0; +25488 132 39 0; +25601 130 68 0; +25699 147 51 88; +25708 145 48 92; +25713 146 68 77; +25726 131 53 0; +25729 129 49 0; +25820 147 50 88; +25840 131 51 0; +25911 130 68 0; +25920 129 48 0; +25951 146 67 69; +25952 147 48 80; +25958 148 39 78; +25961 131 50 0; +25968 145 48 88; +25975 132 41 0; +26079 148 38 80; +26101 132 39 0; +26197 132 38 0; +26197 148 36 72; +26207 146 72 80; +26217 130 67 0; +26327 145 46 80; +26340 129 48 0; +26433 131 48 0; +26447 145 44 88; +26453 146 60 79; +26456 148 48 88; +26457 129 46 0; +26466 130 72 0; +26479 132 36 0; +26564 145 46 79; +26574 129 44 0; +26691 145 34 80; +26692 195 99; +26702 147 77 79; +26703 146 61 80; +26703 148 46 88; +26708 129 46 0; +26718 130 60 0; +26720 132 48 0; +26820 146 60 79; +26844 130 61 0; +26936 146 61 80; +26955 130 60 0; +27048 145 37 80; +27054 146 58 79; +27059 148 49 80; +27064 129 34 0; +27075 130 61 0; +27076 132 46 0; +27141 147 79 88; +27161 131 77 0; +27168 146 63 80; +27170 145 36 80; +27173 129 37 0; +27182 148 48 84; +27187 130 58 0; +27189 132 49 0; +27280 146 60 80; +27291 130 63 0; +27410 146 65 80; +27420 147 80 88; +27425 130 60 0; +27426 145 41 80; +27428 131 79 0; +27430 148 53 94; +27446 129 36 0; +27446 132 48 0; +27768 132 53 0; +27769 129 41 0; +27793 148 53 80; +27799 145 41 88; +27814 147 82 94; +27830 131 80 0; +27852 130 65 0; +27876 132 53 0; +27879 129 41 0; +27903 148 53 79; +27909 145 41 80; +27928 147 80 92; +27934 146 65 88; +27943 131 82 0; +28023 145 44 84; +28025 148 56 84; +28032 129 41 0; +28037 132 53 0; +28139 130 65 0; +28155 147 79 79; +28156 148 55 92; +28158 145 43 88; +28174 129 44 0; +28175 146 63 88; +28175 131 80 0; +28176 132 56 0; +28241 147 80 80; +28256 131 79 0; +28327 147 79 79; +28340 131 80 0; +28411 148 48 88; +28413 132 55 0; +28416 145 36 80; +28425 129 43 0; +28427 147 75 80; +28449 131 79 0; +28537 146 60 80; +28565 130 63 0; +28648 147 72 76; +28654 146 56 88; +28657 130 60 0; +28664 131 75 0; +28762 146 55 80; +28784 130 56 0; +28892 147 77 79; +28894 146 53 88; +28899 145 34 88; +28901 148 46 88; +28907 130 55 0; +28909 129 36 0; +28911 132 48 0; +28914 131 72 0; +29014 146 51 88; +29036 130 53 0; +29144 146 49 80; +29153 147 70 88; +29156 130 51 0; +29182 131 77 0; +29396 145 32 80; +29396 147 72 76; +29407 129 34 0; +29407 148 44 92; +29420 131 70 0; +29425 132 46 0; +29633 147 73 80; +29642 131 72 0; +29643 148 42 80; +29650 145 30 76; +29650 146 54 88; +29661 132 44 0; +29672 130 49 0; +29677 129 32 0; +29761 148 44 92; +29762 131 73 0; +29764 145 32 79; +29777 129 30 0; +29777 132 42 0; +29885 148 46 80; +29896 145 34 88; +29896 147 73 76; +29902 132 44 0; +29920 129 32 0; +30033 131 73 0; +30131 148 44 88; +30140 146 53 92; +30145 147 73 77; +30158 132 46 0; +30161 130 54 0; +30252 148 43 88; +30272 132 44 0; +30343 131 73 0; +30352 130 53 0; +30383 147 72 69; +30384 148 41 80; +30390 145 32 78; +30393 132 43 0; +30400 146 53 88; +30407 129 34 0; +30511 145 31 80; +30533 129 32 0; +30629 129 31 0; +30629 145 29 72; +30639 147 77 80; +30649 131 72 0; +30759 146 51 80; +30772 130 53 0; +30865 132 41 0; +30879 146 49 88; +30885 147 65 79; +30888 145 41 88; +30889 130 51 0; +30898 131 77 0; +30911 129 29 0; +30996 146 51 79; +31006 130 49 0; +31123 146 39 80; +31124 196 47; +31134 148 70 79; +31135 145 39 88; +31135 147 66 80; +31140 130 51 0; +31150 131 65 0; +31152 129 41 0; +31252 147 65 79; +31276 131 66 0; +31368 147 66 80; +31387 131 65 0; +31480 146 42 80; +31486 147 63 79; +31491 145 42 80; +31496 130 39 0; +31507 131 66 0; +31508 129 39 0; +31573 148 72 88; +31593 132 70 0; +31600 147 68 80; +31602 146 41 80; +31605 130 42 0; +31614 145 41 84; +31619 131 63 0; +31621 129 42 0; +31712 147 65 80; +31723 131 68 0; +31842 147 70 80; +31852 148 73 88; +31857 131 65 0; +31858 146 46 80; +31860 132 72 0; +31862 145 46 94; +31878 129 41 0; +31878 130 41 0; +32200 129 46 0; +32201 130 46 0; +32225 145 46 80; +32231 146 46 88; +32246 148 75 94; +32262 132 73 0; +32284 131 70 0; +32308 129 46 0; +32311 130 46 0; +32335 145 46 79; +32341 146 46 80; +32360 148 73 92; +32366 147 70 88; +32375 132 75 0; +32455 146 49 84; +32457 145 49 84; +32464 130 46 0; +32469 129 46 0; +32571 131 70 0; +32587 148 72 79; +32588 145 48 92; +32590 146 48 88; +32606 130 49 0; +32607 147 68 88; +32607 132 73 0; +32608 129 49 0; +32673 148 73 80; +32688 132 72 0; +32759 148 72 79; +32772 132 73 0; +32843 145 41 88; +32845 129 48 0; +32848 146 41 80; +32857 130 48 0; +32859 148 68 80; +32881 132 72 0; +32969 147 65 80; +32997 131 68 0; +33080 148 65 76; +33086 147 61 88; +33089 131 65 0; +33096 132 68 0; +33194 147 60 80; +33216 131 61 0; +33324 148 70 79; +33326 147 58 88; +33331 146 39 88; +33333 145 39 88; +33339 131 60 0; +33341 130 41 0; +33343 129 41 0; +33346 132 65 0; +33446 147 56 88; +33468 131 58 0; +33576 147 54 80; +33585 148 63 88; +33588 131 56 0; +33614 132 70 0; +33828 146 37 80; +33828 148 65 76; +33839 145 37 92; +33839 130 39 0; +33852 132 63 0; +33857 129 39 0; +34065 148 66 80; +34074 132 65 0; +34075 145 35 80; +34082 146 35 76; +34082 147 59 88; +34093 129 37 0; +34104 131 54 0; +34109 130 37 0; +34193 145 37 92; +34194 132 66 0; +34196 146 37 79; +34209 129 35 0; +34209 130 35 0; +34317 145 39 80; +34328 146 39 88; +34328 148 66 76; +34334 129 37 0; +34352 130 37 0; +34465 132 66 0; +34563 145 37 88; +34572 147 58 92; +34577 148 66 77; +34590 129 39 0; +34593 131 59 0; +34684 145 36 88; +34704 129 37 0; +34775 132 66 0; +34784 131 58 0; +34815 148 65 69; +34816 145 34 80; +34822 146 37 78; +34825 129 36 0; +34832 147 58 88; +34839 130 39 0; +34943 146 36 80; +34965 130 37 0; +35061 130 36 0; +35061 146 34 72; +35071 148 70 80; +35081 132 65 0; +35191 147 56 80; +35204 131 58 0; +35297 129 34 0; +35311 147 54 88; +35317 148 58 79; +35320 146 46 88; +35321 131 56 0; +35330 132 70 0; +35343 130 34 0; +35428 147 56 79; +35438 131 54 0; +35555 147 44 80; +35568 146 44 88; +35568 148 59 80; +35573 131 56 0; +35583 132 58 0; +35585 130 46 0; +35685 148 58 79; +35709 132 59 0; +35801 148 59 80; +35820 132 58 0; +35913 147 47 80; +35919 148 56 79; +35924 146 47 80; +35929 131 44 0; +35940 132 59 0; +35941 130 44 0; +36034 148 61 80; +36036 147 46 80; +36039 131 47 0; +36048 146 46 84; +36053 132 56 0; +36055 130 47 0; +36146 148 58 80; +36157 132 61 0; +36276 148 63 80; +36291 132 58 0; +36292 147 51 80; +36297 146 51 94; +36313 130 46 0; +36313 131 46 0; +36635 130 51 0; +36636 131 51 0; +36660 146 51 80; +36666 147 51 88; +36720 132 63 0; +36744 130 51 0; +36747 131 51 0; +36771 146 51 79; +36777 147 51 80; +36803 148 63 88; +36892 147 54 84; +36894 146 54 84; +36901 131 51 0; +36906 130 51 0; +37008 132 63 0; +37026 146 53 92; +37028 147 53 88; +37044 131 54 0; +37045 148 61 88; +37046 130 54 0; +37282 146 46 88; +37284 130 53 0; +37287 147 46 80; +37296 131 53 0; +37409 148 58 80; +37437 132 61 0; +37526 148 54 88; +37529 132 58 0; +37635 148 53 80; +37657 132 54 0; +37767 148 51 88; +37772 147 44 88; +37774 146 44 88; +37780 132 53 0; +37782 131 46 0; +37784 130 46 0; +37888 148 49 88; +37910 132 51 0; +38018 148 47 80; +38031 132 49 0; +38271 147 42 80; +38282 146 42 92; +38282 131 44 0; +38300 130 44 0; +38518 146 40 80; +38525 147 40 76; +38525 148 52 88; +38536 130 42 0; +38547 132 47 0; +38552 131 42 0; +38636 146 42 92; +38639 147 42 79; +38652 130 40 0; +38652 131 40 0; +38760 146 44 80; +38771 147 44 88; +38777 130 42 0; +38795 131 42 0; +39007 146 42 88; +39016 148 51 92; +39034 130 44 0; +39037 132 52 0; +39128 146 41 88; +39148 130 42 0; +39228 132 51 0; +39260 146 39 80; +39266 147 42 78; +39269 130 41 0; +39276 148 51 88; +39283 131 44 0; +39387 147 41 80; +39409 131 42 0; +39505 131 41 0; +39505 147 39 72; +39636 148 49 80; +39649 132 51 0; +39742 130 39 0; +39756 148 47 88; +39766 147 51 88; +39767 132 49 0; +39789 131 39 0; +39874 148 49 79; +39884 132 47 0; +40001 148 37 80; +40014 147 49 88; +40019 132 49 0; +40032 131 51 0; +40362 148 40 80; +40373 147 52 80; +40378 132 37 0; +40391 131 49 0; +40487 148 39 80; +40490 132 40 0; +40499 147 51 84; +40506 131 52 0; +40745 148 44 80; +40750 147 56 94; +40766 131 51 0; +40766 132 39 0; +41088 131 56 0; +41089 132 44 0; +41113 147 56 80; +41119 148 44 88; +41198 131 56 0; +41201 132 44 0; +41225 147 56 79; +41231 148 44 80; +41346 148 47 84; +41348 147 59 84; +41355 132 44 0; +41360 131 56 0; +41481 147 58 92; +41483 148 46 88; +41499 132 47 0; +41501 131 59 0; +41737 147 51 88; +41739 131 58 0; +41742 148 39 80; +41751 132 46 0; +42231 148 37 88; +42233 147 49 88; +42242 132 39 0; +42244 131 51 0; +42732 148 35 80; +42743 147 47 92; +42743 132 37 0; +42761 131 49 0; +42979 147 45 80; +42986 148 33 76; +42997 131 47 0; +43013 132 35 0; +43097 147 47 92; +43100 148 35 79; +43113 131 45 0; +43113 132 33 0; +43221 147 49 80; +43232 148 37 88; +43238 131 47 0; +43256 132 35 0; +43468 147 47 88; +43495 131 49 0; +43590 147 46 88; +43610 131 47 0; +43723 147 44 80; +43729 148 35 78; +43732 131 46 0; +43747 132 37 0; +43851 148 34 80; +43873 132 35 0; +43969 132 34 0; +43969 148 32 72; +44207 131 44 0; +44231 148 44 88; +44254 132 32 0; +44480 148 42 88; +44498 132 44 0; +44840 148 45 80; +44858 132 42 0; +44967 148 44 84; +44974 132 45 0; +45218 148 49 94; +45234 132 44 0; +45556 132 49 0; +45582 148 49 80; +45667 132 49 0; +45695 148 49 79; +45820 148 52 84; +45833 132 49 0; +45954 148 51 92; +45976 132 52 0; +46212 148 44 88; +46214 132 51 0; +46710 148 42 88; +46721 132 44 0; +47221 148 40 92; +47239 132 42 0; +47457 148 38 80; +47476 132 40 0; +47577 148 40 92; +47593 132 38 0; +47701 148 42 80; +47719 132 40 0; +47949 148 40 88; +47976 132 42 0; +48071 148 39 88; +48091 132 40 0; +48204 148 37 80; +48214 132 39 0; +48690 132 37 0; diff --git a/test/cyclone/test1.seq b/test/cyclone/test1.seq new file mode 100644 index 0000000..5b695dc --- /dev/null +++ b/test/cyclone/test1.seq @@ -0,0 +1,1208 @@ +0 193 107; +7 145 71 79; +449 145 73 88; +467 129 71 0; +730 145 74 88; +737 129 73 0; +1125 145 76 94; +1140 129 74 0; +1238 145 74 92; +1251 129 76 0; +1464 145 73 79; +1484 129 74 0; +1549 145 74 80; +1562 129 73 0; +1632 145 73 79; +1642 129 74 0; +1730 145 69 80; +1750 129 73 0; +1947 145 66 76; +1962 129 69 0; +2188 145 71 79; +2211 129 66 0; +2447 145 64 88; +2475 129 71 0; +2688 145 66 76; +2711 129 64 0; +2921 145 67 80; +2928 129 66 0; +3050 129 67 0; +3182 145 67 76; +3317 129 67 0; +3428 145 67 77; +3625 129 67 0; +3664 145 66 69; +3921 145 71 80; +3928 129 66 0; +4164 145 59 79; +4177 129 71 0; +4403 194 98; +4410 146 76 79; +4410 145 60 80; +4423 129 59 0; +4524 145 59 79; +4547 129 60 0; +4638 145 60 80; +4656 129 59 0; +4754 145 57 79; +4774 129 60 0; +4839 146 78 88; +4857 130 76 0; +4862 145 62 80; +4880 129 57 0; +4971 145 59 80; +4981 129 62 0; +5098 145 64 80; +5105 146 79 88; +5107 129 59 0; +5109 130 78 0; +5497 146 81 94; +5512 130 79 0; +5532 129 64 0; +5610 146 79 92; +5615 145 64 88; +5622 130 81 0; +5819 129 64 0; +5834 146 78 79; +5854 145 62 88; +5854 130 79 0; +5919 146 79 80; +5932 130 78 0; +6002 146 78 79; +6012 130 79 0; +6100 146 74 80; +6120 130 78 0; +6205 145 59 80; +6231 129 62 0; +6311 146 71 76; +6316 145 55 88; +6318 129 59 0; +6323 130 74 0; +6419 145 54 80; +6439 129 55 0; +6545 146 76 79; +6545 145 52 88; +6558 129 54 0; +6565 130 71 0; +6663 145 50 88; +6683 129 52 0; +6789 145 48 80; +6796 146 69 88; +6798 129 50 0; +6821 130 76 0; +7034 146 71 76; +7057 130 69 0; +7267 146 72 80; +7274 130 71 0; +7281 145 53 88; +7301 129 48 0; +7389 130 72 0; +7521 146 72 76; +7656 130 72 0; +7762 145 52 92; +7764 146 72 77; +7779 129 53 0; +7961 130 72 0; +7968 129 52 0; +7996 146 71 69; +8014 145 52 88; +8253 146 76 80; +8260 130 71 0; +8369 145 50 80; +8379 129 52 0; +8485 145 48 88; +8490 146 64 79; +8492 129 50 0; +8499 130 76 0; +8595 145 50 79; +8602 129 48 0; +8716 145 38 80; +8716 195 74; +8723 147 81 79; +8723 146 65 80; +8725 129 50 0; +8732 130 64 0; +8833 146 64 79; +8856 130 65 0; +8947 146 65 80; +8965 130 64 0; +9056 145 41 80; +9061 146 62 79; +9068 129 38 0; +9078 130 65 0; +9143 147 83 88; +9161 131 81 0; +9166 146 67 80; +9166 145 40 80; +9168 129 41 0; +9181 130 62 0; +9272 146 64 80; +9282 130 67 0; +9399 146 69 80; +9406 147 84 88; +9408 130 64 0; +9408 145 45 80; +9408 131 83 0; +9426 129 40 0; +9748 129 45 0; +9776 145 45 88; +9789 147 86 94; +9804 131 84 0; +9824 130 69 0; +9850 129 45 0; +9878 145 45 80; +9896 147 84 92; +9901 146 69 88; +9908 131 86 0; +9986 145 48 84; +9993 129 45 0; +10099 130 69 0; +10114 147 83 79; +10116 145 47 88; +10131 129 48 0; +10131 146 67 88; +10131 131 84 0; +10196 147 84 80; +10209 131 83 0; +10279 147 83 79; +10289 131 84 0; +10364 145 40 80; +10371 129 47 0; +10371 147 79 80; +10391 131 83 0; +10476 146 64 80; +10502 130 67 0; +10582 147 76 76; +10587 146 60 88; +10589 130 64 0; +10594 131 79 0; +10690 146 59 80; +10710 130 60 0; +10816 147 81 79; +10816 146 57 88; +10818 145 38 88; +10825 130 59 0; +10825 129 40 0; +10830 131 76 0; +10928 146 55 88; +10948 130 57 0; +11054 146 53 80; +11061 147 74 88; +11063 130 55 0; +11086 131 81 0; +11299 145 36 80; +11299 147 76 76; +11309 129 38 0; +11319 131 74 0; +11529 147 77 80; +11536 131 76 0; +11543 145 34 76; +11543 146 58 88; +11563 130 53 0; +11565 129 36 0; +11648 131 77 0; +11648 145 36 79; +11658 129 34 0; +11775 145 38 88; +11775 147 77 76; +11798 129 36 0; +11909 131 77 0; +12015 146 57 92; +12017 147 77 77; +12032 130 58 0; +12214 131 77 0; +12221 130 57 0; +12249 147 76 69; +12254 145 36 78; +12264 146 57 88; +12269 129 38 0; +12370 145 35 80; +12390 129 36 0; +12483 129 35 0; +12483 145 33 72; +12490 147 81 80; +12497 131 76 0; +12606 146 55 80; +12616 130 57 0; +12722 146 53 88; +12727 147 69 79; +12729 145 45 88; +12729 130 55 0; +12736 131 81 0; +12746 129 33 0; +12829 146 55 79; +12836 130 53 0; +12950 146 43 80; +12950 196 38; +12957 148 74 79; +12957 145 43 88; +12957 147 70 80; +12959 130 55 0; +12966 131 69 0; +12966 129 45 0; +13064 147 69 79; +13087 131 70 0; +13178 147 70 80; +13196 131 69 0; +13287 146 46 80; +13292 147 67 79; +13294 145 46 80; +13296 130 43 0; +13306 131 70 0; +13306 129 43 0; +13368 148 76 88; +13386 132 74 0; +13391 147 72 80; +13391 146 45 80; +13393 130 46 0; +13400 145 45 84; +13402 131 67 0; +13402 129 46 0; +13490 147 69 80; +13500 131 72 0; +13617 147 74 80; +13624 148 77 88; +13626 131 69 0; +13626 146 50 80; +13626 132 76 0; +13626 145 50 94; +13641 129 45 0; +13641 130 45 0; +13961 129 50 0; +13961 130 50 0; +13984 145 50 80; +13989 146 50 88; +14002 148 79 94; +14017 132 77 0; +14037 131 74 0; +14060 129 50 0; +14062 130 50 0; +14085 145 50 79; +14090 146 50 80; +14108 148 77 92; +14113 147 74 88; +14120 132 79 0; +14198 146 53 84; +14198 145 53 84; +14203 130 50 0; +14205 129 50 0; +14306 131 74 0; +14321 148 76 79; +14321 145 52 92; +14321 146 52 88; +14336 130 53 0; +14336 147 72 88; +14336 132 77 0; +14336 129 53 0; +14398 148 77 80; +14411 132 76 0; +14481 148 76 79; +14491 132 77 0; +14561 145 45 88; +14561 129 52 0; +14563 146 45 80; +14570 130 52 0; +14570 148 72 80; +14590 132 76 0; +14675 147 69 80; +14701 131 72 0; +14781 148 69 76; +14786 147 65 88; +14788 131 69 0; +14793 132 72 0; +14889 147 64 80; +14909 131 65 0; +15015 148 74 79; +15015 147 62 88; +15017 146 43 88; +15017 145 43 88; +15022 131 64 0; +15022 130 45 0; +15022 129 45 0; +15024 132 69 0; +15122 147 60 88; +15142 131 62 0; +15248 147 58 80; +15255 148 67 88; +15257 131 60 0; +15280 132 74 0; +15493 146 41 80; +15493 148 69 76; +15503 145 41 92; +15503 130 43 0; +15513 132 67 0; +15515 129 43 0; +15720 148 70 80; +15727 132 69 0; +15727 145 39 80; +15732 146 39 76; +15732 147 63 88; +15742 129 41 0; +15752 131 58 0; +15754 130 41 0; +15837 145 41 92; +15837 132 70 0; +15837 146 41 79; +15847 129 39 0; +15847 130 39 0; +15953 145 43 80; +15963 146 43 88; +15963 148 70 76; +15968 129 41 0; +15983 130 41 0; +16094 132 70 0; +16190 145 41 88; +16197 147 62 92; +16199 148 70 77; +16209 129 43 0; +16211 131 63 0; +16299 145 40 88; +16317 129 41 0; +16387 132 70 0; +16394 131 62 0; +16422 148 69 69; +16422 145 38 80; +16427 146 41 78; +16429 129 40 0; +16434 147 62 88; +16439 130 43 0; +16540 146 40 80; +16560 130 41 0; +16653 130 40 0; +16653 146 38 72; +16660 148 74 80; +16667 132 69 0; +16776 147 60 80; +16786 131 62 0; +16877 129 38 0; +16890 147 58 88; +16895 148 62 79; +16897 146 50 88; +16897 131 60 0; +16904 132 74 0; +16914 130 38 0; +16997 147 60 79; +17004 131 58 0; +17118 147 48 80; +17118 193 44; +17125 145 67 79; +17125 146 48 88; +17125 148 63 80; +17127 131 60 0; +17134 132 62 0; +17134 130 50 0; +17232 148 62 79; +17255 132 63 0; +17346 148 63 80; +17364 132 62 0; +17455 147 51 80; +17460 148 60 79; +17462 146 51 80; +17464 131 48 0; +17474 132 63 0; +17474 130 48 0; +17536 145 69 88; +17554 129 67 0; +17559 148 65 80; +17559 147 50 80; +17561 131 51 0; +17568 146 50 84; +17570 132 60 0; +17570 130 51 0; +17658 148 62 80; +17668 132 65 0; +17785 148 67 80; +17792 145 70 88; +17794 132 62 0; +17794 147 55 80; +17794 129 69 0; +17794 146 55 94; +17809 130 50 0; +17809 131 50 0; +18129 130 55 0; +18129 131 55 0; +18152 146 55 80; +18157 147 55 88; +18170 145 72 94; +18185 129 70 0; +18205 132 67 0; +18228 130 55 0; +18230 131 55 0; +18253 146 55 79; +18258 147 55 80; +18276 145 70 92; +18281 148 67 88; +18288 129 72 0; +18366 147 58 84; +18366 146 58 84; +18371 131 55 0; +18373 130 55 0; +18474 132 67 0; +18489 145 69 79; +18489 146 57 92; +18489 147 57 88; +18504 131 58 0; +18504 129 70 0; +18504 148 65 88; +18504 130 58 0; +18566 145 70 80; +18579 129 69 0; +18649 145 69 79; +18659 129 70 0; +18729 146 50 88; +18729 130 57 0; +18731 147 50 80; +18738 131 57 0; +18738 145 65 80; +18758 129 69 0; +18843 148 62 80; +18869 132 65 0; +18949 145 62 76; +18954 148 58 88; +18956 132 62 0; +18961 129 65 0; +19057 148 57 80; +19077 132 58 0; +19183 145 67 79; +19183 148 55 88; +19185 147 48 88; +19185 146 48 88; +19190 132 57 0; +19190 131 50 0; +19190 130 50 0; +19192 129 62 0; +19290 148 53 88; +19310 132 55 0; +19416 148 51 80; +19423 145 60 88; +19425 132 53 0; +19448 129 67 0; +19661 145 62 76; +19661 147 46 80; +19671 146 46 92; +19671 131 48 0; +19681 129 60 0; +19683 130 48 0; +19888 145 63 80; +19895 129 62 0; +19895 146 44 80; +19900 147 44 76; +19900 148 56 88; +19910 130 46 0; +19920 132 51 0; +19922 131 46 0; +20005 146 46 92; +20005 129 63 0; +20005 147 46 79; +20015 130 44 0; +20015 131 44 0; +20121 146 48 80; +20131 145 63 76; +20131 147 48 88; +20136 130 46 0; +20151 131 46 0; +20262 129 63 0; +20358 146 46 88; +20365 148 55 92; +20367 145 63 77; +20377 130 48 0; +20379 132 56 0; +20467 146 45 88; +20485 130 46 0; +20555 129 63 0; +20562 132 55 0; +20590 145 62 69; +20590 146 43 80; +20595 147 46 78; +20597 130 45 0; +20602 148 55 88; +20607 131 48 0; +20708 147 45 80; +20728 131 46 0; +20821 131 45 0; +20821 147 43 72; +20828 145 67 80; +20835 129 62 0; +20944 148 53 80; +20954 132 55 0; +21045 130 43 0; +21058 148 51 88; +21063 145 55 79; +21065 147 55 88; +21065 132 53 0; +21072 129 67 0; +21082 131 43 0; +21165 148 53 79; +21172 132 51 0; +21286 148 41 80; +21286 194 66; +21293 146 72 79; +21293 145 56 80; +21293 147 53 88; +21295 132 53 0; +21302 129 55 0; +21302 131 55 0; +21400 145 55 79; +21423 129 56 0; +21514 145 56 80; +21532 129 55 0; +21623 148 44 80; +21628 145 53 79; +21630 147 56 80; +21632 132 41 0; +21642 129 56 0; +21642 131 53 0; +21704 146 74 88; +21722 130 72 0; +21727 145 58 80; +21727 148 43 80; +21729 132 44 0; +21736 147 55 84; +21738 129 53 0; +21738 131 56 0; +21826 145 55 80; +21836 129 58 0; +21953 145 60 80; +21960 146 75 88; +21962 129 55 0; +21962 148 48 80; +21962 130 74 0; +21962 147 60 94; +21977 131 55 0; +21977 132 43 0; +22297 131 60 0; +22297 132 48 0; +22320 147 60 80; +22325 148 48 88; +22338 146 77 94; +22353 130 75 0; +22373 129 60 0; +22396 131 60 0; +22398 132 48 0; +22421 147 60 79; +22426 148 48 80; +22444 146 75 92; +22449 145 60 88; +22456 130 77 0; +22534 148 51 84; +22534 147 63 84; +22539 132 48 0; +22541 131 60 0; +22642 129 60 0; +22657 146 74 79; +22657 147 62 92; +22657 148 50 88; +22672 132 51 0; +22672 145 58 88; +22672 130 75 0; +22672 131 63 0; +22734 146 75 80; +22747 130 74 0; +22817 146 74 79; +22827 130 75 0; +22897 147 55 88; +22897 131 62 0; +22899 148 43 80; +22906 132 50 0; +22906 146 70 80; +22926 130 74 0; +23011 145 55 80; +23037 129 58 0; +23117 146 67 76; +23122 145 51 88; +23124 129 55 0; +23129 130 70 0; +23225 145 50 80; +23245 129 51 0; +23351 146 72 79; +23351 145 48 88; +23353 148 41 88; +23353 147 53 88; +23358 129 50 0; +23358 132 43 0; +23358 131 55 0; +23360 130 67 0; +23458 145 46 88; +23478 129 48 0; +23584 145 44 80; +23591 146 65 88; +23593 129 46 0; +23616 130 72 0; +23829 146 67 76; +23829 148 39 80; +23839 147 51 92; +23839 132 41 0; +23849 130 65 0; +23851 131 53 0; +24056 146 68 80; +24063 130 67 0; +24063 147 49 80; +24068 145 49 88; +24068 148 37 76; +24078 131 51 0; +24088 129 44 0; +24090 132 39 0; +24173 147 51 92; +24173 130 68 0; +24173 148 39 79; +24183 131 49 0; +24183 132 37 0; +24289 147 53 80; +24299 146 68 76; +24299 148 41 88; +24304 131 51 0; +24319 132 39 0; +24430 130 68 0; +24526 147 51 88; +24533 145 48 92; +24535 146 68 77; +24545 131 53 0; +24547 129 49 0; +24635 147 50 88; +24653 131 51 0; +24723 130 68 0; +24730 129 48 0; +24758 146 67 69; +24758 147 48 80; +24763 148 39 78; +24765 131 50 0; +24770 145 48 88; +24775 132 41 0; +24876 148 38 80; +24896 132 39 0; +24989 132 38 0; +24989 148 36 72; +24996 146 72 80; +25003 130 67 0; +25112 145 46 80; +25122 129 48 0; +25213 131 48 0; +25226 145 44 88; +25231 146 60 79; +25233 148 48 88; +25233 129 46 0; +25240 130 72 0; +25250 132 36 0; +25333 145 46 79; +25340 129 44 0; +25454 145 34 80; +25454 195 99; +25461 147 77 79; +25461 146 61 80; +25461 148 46 88; +25463 129 46 0; +25470 130 60 0; +25470 132 48 0; +25568 146 60 79; +25591 130 61 0; +25682 146 61 80; +25700 130 60 0; +25791 145 37 80; +25796 146 58 79; +25798 148 49 80; +25800 129 34 0; +25810 130 61 0; +25810 132 46 0; +25872 147 79 88; +25890 131 77 0; +25895 146 63 80; +25895 145 36 80; +25897 129 37 0; +25904 148 48 84; +25906 130 58 0; +25906 132 49 0; +25994 146 60 80; +26004 130 63 0; +26121 146 65 80; +26128 147 80 88; +26130 130 60 0; +26130 145 41 80; +26130 131 79 0; +26130 148 53 94; +26145 129 36 0; +26145 132 48 0; +26465 132 53 0; +26465 129 41 0; +26488 148 53 80; +26493 145 41 88; +26506 147 82 94; +26521 131 80 0; +26541 130 65 0; +26564 132 53 0; +26566 129 41 0; +26589 148 53 79; +26594 145 41 80; +26612 147 80 92; +26617 146 65 88; +26624 131 82 0; +26702 145 44 84; +26702 148 56 84; +26707 129 41 0; +26709 132 53 0; +26810 130 65 0; +26825 147 79 79; +26825 148 55 92; +26825 145 43 88; +26840 129 44 0; +26840 146 63 88; +26840 131 80 0; +26840 132 56 0; +26902 147 80 80; +26915 131 79 0; +26985 147 79 79; +26995 131 80 0; +27065 148 48 88; +27065 132 55 0; +27067 145 36 80; +27074 129 43 0; +27074 147 75 80; +27094 131 79 0; +27179 146 60 80; +27205 130 63 0; +27285 147 72 76; +27290 146 56 88; +27292 130 60 0; +27297 131 75 0; +27393 146 55 80; +27413 130 56 0; +27519 147 77 79; +27519 146 53 88; +27521 145 34 88; +27521 148 46 88; +27526 130 55 0; +27526 129 36 0; +27526 132 48 0; +27528 131 72 0; +27626 146 51 88; +27646 130 53 0; +27752 146 49 80; +27759 147 70 88; +27761 130 51 0; +27784 131 77 0; +27997 145 32 80; +27997 147 72 76; +28007 129 34 0; +28007 148 44 92; +28017 131 70 0; +28019 132 46 0; +28224 147 73 80; +28231 131 72 0; +28231 148 42 80; +28236 145 30 76; +28236 146 54 88; +28246 132 44 0; +28256 130 49 0; +28258 129 32 0; +28341 148 44 92; +28341 131 73 0; +28341 145 32 79; +28351 129 30 0; +28351 132 42 0; +28457 148 46 80; +28467 145 34 88; +28467 147 73 76; +28472 132 44 0; +28487 129 32 0; +28598 131 73 0; +28694 148 44 88; +28701 146 53 92; +28703 147 73 77; +28713 132 46 0; +28715 130 54 0; +28803 148 43 88; +28821 132 44 0; +28891 131 73 0; +28898 130 53 0; +28926 147 72 69; +28926 148 41 80; +28931 145 32 78; +28933 132 43 0; +28938 146 53 88; +28943 129 34 0; +29044 145 31 80; +29064 129 32 0; +29157 129 31 0; +29157 145 29 72; +29164 147 77 80; +29171 131 72 0; +29280 146 51 80; +29290 130 53 0; +29381 132 41 0; +29394 146 49 88; +29399 147 65 79; +29401 145 41 88; +29401 130 51 0; +29408 131 77 0; +29418 129 29 0; +29501 146 51 79; +29508 130 49 0; +29622 146 39 80; +29622 196 47; +29629 148 70 79; +29629 145 39 88; +29629 147 66 80; +29631 130 51 0; +29638 131 65 0; +29638 129 41 0; +29736 147 65 79; +29759 131 66 0; +29850 147 66 80; +29868 131 65 0; +29959 146 42 80; +29964 147 63 79; +29966 145 42 80; +29968 130 39 0; +29978 131 66 0; +29978 129 39 0; +30040 148 72 88; +30058 132 70 0; +30063 147 68 80; +30063 146 41 80; +30065 130 42 0; +30072 145 41 84; +30074 131 63 0; +30074 129 42 0; +30162 147 65 80; +30172 131 68 0; +30289 147 70 80; +30296 148 73 88; +30298 131 65 0; +30298 146 46 80; +30298 132 72 0; +30298 145 46 94; +30313 129 41 0; +30313 130 41 0; +30633 129 46 0; +30633 130 46 0; +30656 145 46 80; +30661 146 46 88; +30674 148 75 94; +30689 132 73 0; +30709 131 70 0; +30732 129 46 0; +30734 130 46 0; +30757 145 46 79; +30762 146 46 80; +30780 148 73 92; +30785 147 70 88; +30792 132 75 0; +30870 146 49 84; +30870 145 49 84; +30875 130 46 0; +30877 129 46 0; +30978 131 70 0; +30993 148 72 79; +30993 145 48 92; +30993 146 48 88; +31008 130 49 0; +31008 147 68 88; +31008 132 73 0; +31008 129 49 0; +31070 148 73 80; +31083 132 72 0; +31153 148 72 79; +31163 132 73 0; +31233 145 41 88; +31233 129 48 0; +31235 146 41 80; +31242 130 48 0; +31242 148 68 80; +31262 132 72 0; +31347 147 65 80; +31373 131 68 0; +31453 148 65 76; +31458 147 61 88; +31460 131 65 0; +31465 132 68 0; +31561 147 60 80; +31581 131 61 0; +31687 148 70 79; +31687 147 58 88; +31689 146 39 88; +31689 145 39 88; +31694 131 60 0; +31694 130 41 0; +31694 129 41 0; +31696 132 65 0; +31794 147 56 88; +31814 131 58 0; +31920 147 54 80; +31927 148 63 88; +31929 131 56 0; +31952 132 70 0; +32165 146 37 80; +32165 148 65 76; +32175 145 37 92; +32175 130 39 0; +32185 132 63 0; +32187 129 39 0; +32392 148 66 80; +32399 132 65 0; +32399 145 35 80; +32404 146 35 76; +32404 147 59 88; +32414 129 37 0; +32424 131 54 0; +32426 130 37 0; +32509 145 37 92; +32509 132 66 0; +32509 146 37 79; +32519 129 35 0; +32519 130 35 0; +32625 145 39 80; +32635 146 39 88; +32635 148 66 76; +32640 129 37 0; +32655 130 37 0; +32766 132 66 0; +32862 145 37 88; +32869 147 58 92; +32871 148 66 77; +32881 129 39 0; +32883 131 59 0; +32971 145 36 88; +32989 129 37 0; +33059 132 66 0; +33066 131 58 0; +33094 148 65 69; +33094 145 34 80; +33099 146 37 78; +33101 129 36 0; +33106 147 58 88; +33111 130 39 0; +33212 146 36 80; +33232 130 37 0; +33325 130 36 0; +33325 146 34 72; +33332 148 70 80; +33339 132 65 0; +33448 147 56 80; +33458 131 58 0; +33549 129 34 0; +33562 147 54 88; +33567 148 58 79; +33569 146 46 88; +33569 131 56 0; +33576 132 70 0; +33586 130 34 0; +33669 147 56 79; +33676 131 54 0; +33790 147 44 80; +33800 146 44 88; +33800 148 59 80; +33802 131 56 0; +33809 132 58 0; +33809 130 46 0; +33907 148 58 79; +33930 132 59 0; +34021 148 59 80; +34039 132 58 0; +34130 147 47 80; +34135 148 56 79; +34137 146 47 80; +34139 131 44 0; +34149 132 59 0; +34149 130 44 0; +34240 148 61 80; +34240 147 46 80; +34242 131 47 0; +34249 146 46 84; +34251 132 56 0; +34251 130 47 0; +34339 148 58 80; +34349 132 61 0; +34466 148 63 80; +34479 132 58 0; +34479 147 51 80; +34481 146 51 94; +34496 130 46 0; +34496 131 46 0; +34816 130 51 0; +34816 131 51 0; +34839 146 51 80; +34844 147 51 88; +34896 132 63 0; +34919 130 51 0; +34921 131 51 0; +34944 146 51 79; +34949 147 51 80; +34972 148 63 88; +35060 147 54 84; +35060 146 54 84; +35065 131 51 0; +35067 130 51 0; +35168 132 63 0; +35183 146 53 92; +35183 147 53 88; +35198 131 54 0; +35198 148 61 88; +35198 130 54 0; +35432 146 46 88; +35432 130 53 0; +35434 147 46 80; +35441 131 53 0; +35552 148 58 80; +35578 132 61 0; +35666 148 54 88; +35668 132 58 0; +35772 148 53 80; +35792 132 54 0; +35901 148 51 88; +35903 147 44 88; +35903 146 44 88; +35908 132 53 0; +35908 131 46 0; +35908 130 46 0; +36009 148 49 88; +36029 132 51 0; +36135 148 47 80; +36145 132 49 0; +36384 147 42 80; +36394 146 42 92; +36394 131 44 0; +36409 130 44 0; +36625 146 40 80; +36630 147 40 76; +36630 148 52 88; +36640 130 42 0; +36650 132 47 0; +36652 131 42 0; +36735 146 42 92; +36737 147 42 79; +36747 130 40 0; +36747 131 40 0; +36853 146 44 80; +36863 147 44 88; +36868 130 42 0; +36883 131 42 0; +37093 146 42 88; +37100 148 51 92; +37115 130 44 0; +37117 132 52 0; +37205 146 41 88; +37223 130 42 0; +37301 132 51 0; +37332 146 39 80; +37337 147 42 78; +37339 130 41 0; +37344 148 51 88; +37349 131 44 0; +37450 147 41 80; +37470 131 42 0; +37563 131 41 0; +37563 147 39 72; +37693 148 49 80; +37703 132 51 0; +37794 130 39 0; +37807 148 47 88; +37814 147 51 88; +37814 132 49 0; +37834 131 39 0; +37917 148 49 79; +37924 132 47 0; +38038 148 37 80; +38048 147 49 88; +38050 132 49 0; +38060 131 51 0; +38388 148 40 80; +38398 147 52 80; +38400 132 37 0; +38410 131 49 0; +38503 148 39 80; +38505 132 40 0; +38512 147 51 84; +38517 131 52 0; +38753 148 44 80; +38755 147 56 94; +38770 131 51 0; +38770 132 39 0; +39090 131 56 0; +39090 132 44 0; +39113 147 56 80; +39118 148 44 88; +39196 131 56 0; +39198 132 44 0; +39221 147 56 79; +39226 148 44 80; +39340 148 47 84; +39340 147 59 84; +39345 132 44 0; +39347 131 56 0; +39466 147 58 92; +39466 148 46 88; +39481 132 47 0; +39481 131 59 0; +39715 147 51 88; +39715 131 58 0; +39717 148 39 80; +39724 132 46 0; +40203 148 37 88; +40203 147 49 88; +40210 132 39 0; +40210 131 51 0; +40696 148 35 80; +40706 147 47 92; +40706 132 37 0; +40721 131 49 0; +40937 147 45 80; +40942 148 33 76; +40952 131 47 0; +40967 132 35 0; +41050 147 47 92; +41052 148 35 79; +41062 131 45 0; +41062 132 33 0; +41168 147 49 80; +41178 148 37 88; +41183 131 47 0; +41198 132 35 0; +41408 147 47 88; +41434 131 49 0; +41527 147 46 88; +41545 131 47 0; +41656 147 44 80; +41661 148 35 78; +41663 131 46 0; +41676 132 37 0; +41777 148 34 80; +41797 132 35 0; +41890 132 34 0; +41890 148 32 72; +42126 131 44 0; +42149 148 44 88; +42169 132 32 0; +42392 148 42 88; +42407 132 44 0; +42748 148 45 80; +42763 132 42 0; +42869 148 44 84; +42874 132 45 0; +43116 148 49 94; +43131 132 44 0; +43451 132 49 0; +43474 148 49 80; +43557 132 49 0; +43583 148 49 79; +43708 148 52 84; +43718 132 49 0; +43837 148 51 92; +43857 132 52 0; +44091 148 44 88; +44091 132 51 0; +44585 148 42 88; +44595 132 44 0; +45095 148 40 92; +45110 132 42 0; +45326 148 38 80; +45344 132 40 0; +45442 148 40 92; +45457 132 38 0; +45563 148 42 80; +45578 132 40 0; +45807 148 40 88; +45833 132 42 0; +45926 148 39 88; +45944 132 40 0; +46055 148 37 80; +46062 132 39 0; +46535 132 37 0; diff --git a/test/cyclone/testmess-reentrant.pd b/test/cyclone/testmess-reentrant.pd new file mode 100644 index 0000000..afac922 --- /dev/null +++ b/test/cyclone/testmess-reentrant.pd @@ -0,0 +1,25 @@ +#N canvas 326 112 405 388 12; +#X obj 67 328 print; +#X obj 67 57 t a b; +#X obj 67 136 spigot; +#X msg 193 95 1; +#X msg 194 136 0; +#X msg 117 220 -9 -8 -7 -6 -5 -4 -3 -2 -1; +#X msg 67 19 test this mess; +#X msg 92 254 test; +#X obj 92 290 testmess 16 heap; +#X obj 67 95 testmess 8; +#X obj 67 181 t a b b b; +#X connect 1 0 9 0; +#X connect 1 1 3 0; +#X connect 2 0 10 0; +#X connect 3 0 2 1; +#X connect 4 0 2 1; +#X connect 5 0 9 0; +#X connect 6 0 1 0; +#X connect 7 0 8 0; +#X connect 9 0 2 0; +#X connect 10 0 0 0; +#X connect 10 1 7 0; +#X connect 10 2 5 0; +#X connect 10 3 4 0; diff --git a/test/cyclone/testmess-test.pd b/test/cyclone/testmess-test.pd new file mode 100644 index 0000000..442ffc3 --- /dev/null +++ b/test/cyclone/testmess-test.pd @@ -0,0 +1,69 @@ +#N canvas 319 97 771 509 12; +#X obj 97 235 until; +#X msg 97 266 test; +#X obj 68 202 t b 0 b; +#X obj 62 371 realtime; +#X floatatom 62 411 0 0 0; +#X obj 346 235 until; +#X msg 346 266 test; +#X obj 317 202 t b 0 b; +#X obj 311 371 realtime; +#X floatatom 311 411 0 0 0; +#X obj 614 235 until; +#X msg 614 266 test; +#X obj 579 371 realtime; +#X floatatom 579 411 0 0 0; +#X obj 317 49 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 +; +#X obj 317 18 loadbang; +#X obj 346 299 testmess 1 heap; +#X obj 346 332 testmess 1 heap; +#X obj 614 332 testmess 1; +#X obj 614 299 testmess 1; +#X obj 97 299 testmess 1 stack; +#X obj 97 332 testmess 1 stack; +#X msg 585 166 1000; +#X msg 317 166 1000; +#X msg 68 166 1000; +#X msg 416 239 set \$1; +#X obj 317 112 t b b; +#X obj 585 202 t b 0 b; +#X obj 317 79 metro 500; +#X floatatom 501 112 5 0 0; +#X obj 416 202 random 120; +#X connect 0 0 1 0; +#X connect 1 0 20 0; +#X connect 2 0 3 1; +#X connect 2 1 0 0; +#X connect 2 2 3 0; +#X connect 3 0 4 0; +#X connect 5 0 6 0; +#X connect 6 0 16 0; +#X connect 7 0 8 1; +#X connect 7 1 5 0; +#X connect 7 2 8 0; +#X connect 8 0 9 0; +#X connect 10 0 11 0; +#X connect 11 0 19 0; +#X connect 12 0 13 0; +#X connect 14 0 28 0; +#X connect 15 0 14 0; +#X connect 16 0 17 0; +#X connect 19 0 18 0; +#X connect 20 0 21 0; +#X connect 22 0 27 0; +#X connect 23 0 7 0; +#X connect 24 0 2 0; +#X connect 25 0 16 0; +#X connect 25 0 19 0; +#X connect 25 0 20 0; +#X connect 26 0 24 0; +#X connect 26 0 22 0; +#X connect 26 0 23 0; +#X connect 26 1 30 0; +#X connect 27 0 12 1; +#X connect 27 1 10 0; +#X connect 27 2 12 0; +#X connect 28 0 26 0; +#X connect 29 0 30 1; +#X connect 30 0 25 0; diff --git a/test/cyclone/thresh-test.pd b/test/cyclone/thresh-test.pd new file mode 100644 index 0000000..35e8ab7 --- /dev/null +++ b/test/cyclone/thresh-test.pd @@ -0,0 +1,41 @@ +#N canvas 415 237 602 431 12; +#X obj 339 290 print; +#X msg 339 173 1 test \, 2 test \, 3 test; +#X obj 339 256 thresh; +#X msg 472 218 300; +#X msg 516 218 1000; +#X msg 388 218 0; +#X msg 430 218 10; +#X msg 276 173 99; +#X msg 315 55 33; +#X obj 315 129 pipe 1; +#X obj 315 89 t 0 0; +#X obj 87 206 pipe 900; +#X msg 154 173 900; +#X msg 199 173 1000; +#X obj 87 89 t b b b; +#X msg 87 129 12; +#X msg 175 129 11; +#X msg 130 129 0; +#X msg 87 55 bang; +#X connect 1 0 2 0; +#X connect 2 0 0 0; +#X connect 3 0 2 1; +#X connect 4 0 2 1; +#X connect 5 0 2 1; +#X connect 6 0 2 1; +#X connect 7 0 2 0; +#X connect 8 0 10 0; +#X connect 9 0 2 0; +#X connect 10 0 9 0; +#X connect 10 1 2 0; +#X connect 11 0 2 0; +#X connect 12 0 11 1; +#X connect 13 0 11 1; +#X connect 14 0 15 0; +#X connect 14 1 17 0; +#X connect 14 2 16 0; +#X connect 15 0 11 0; +#X connect 16 0 2 0; +#X connect 17 0 2 1; +#X connect 18 0 14 0; diff --git a/test/cyclone/tosymbol-test.pd b/test/cyclone/tosymbol-test.pd new file mode 100644 index 0000000..f207831 --- /dev/null +++ b/test/cyclone/tosymbol-test.pd @@ -0,0 +1,44 @@ +#N canvas 200 14 639 535 12; +#X obj 190 190 tosymbol; +#X msg 201 84 test; +#X obj 190 221 print; +#X msg 190 51 symbol test; +#X msg 259 84 bang; +#X msg 265 150 1 2 3; +#X msg 132 84 -0.99; +#X msg 265 119 one two three; +#X obj 28 221 prepend set; +#X msg 28 257 test; +#X msg 26 84 separator; +#X msg 26 115 separator /; +#X msg 405 119 one 2 3; +#X msg 341 150 1 two three; +#X msg 26 146 separator ----; +#X obj 329 51 testmess 300; +#X msg 414 20 test; +#X msg 329 20 7e+10; +#X msg 264 20 bang; +#X obj 478 51 testmess 3000; +#X msg 478 20 huge mess; +#X obj 478 82 print; +#X connect 0 0 2 0; +#X connect 0 0 8 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 0; +#X connect 7 0 0 0; +#X connect 8 0 9 0; +#X connect 10 0 0 0; +#X connect 11 0 0 0; +#X connect 12 0 0 0; +#X connect 13 0 0 0; +#X connect 14 0 0 0; +#X connect 15 0 0 0; +#X connect 16 0 15 0; +#X connect 17 0 15 0; +#X connect 18 0 15 0; +#X connect 19 0 0 0; +#X connect 19 0 21 0; +#X connect 20 0 19 0; diff --git a/test/cyclone/train-test.pd b/test/cyclone/train-test.pd new file mode 100644 index 0000000..cbf6c4a --- /dev/null +++ b/test/cyclone/train-test.pd @@ -0,0 +1,17 @@ +#N canvas 450 299 450 300 12; +#X floatatom 71 50 5 0 0 0 - - -; +#X floatatom 95 77 5 0 0 0 - - -; +#X floatatom 120 108 5 0 0 0 - - -; +#X floatatom 71 229 5 0 0 0 - - -; +#X obj 158 229 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 +-1; +#X obj 201 187 capture~; +#X obj 71 144 train~; +#X obj 71 187 Snapshot~ 20; +#X connect 0 0 6 0; +#X connect 1 0 6 1; +#X connect 2 0 6 2; +#X connect 6 0 5 0; +#X connect 6 0 7 0; +#X connect 6 1 4 0; +#X connect 7 0 3 0; diff --git a/test/cyclone/trig-test.pd b/test/cyclone/trig-test.pd new file mode 100644 index 0000000..b4888f8 --- /dev/null +++ b/test/cyclone/trig-test.pd @@ -0,0 +1,66 @@ +#N canvas 337 140 550 476 12; +#X obj 171 59 acos; +#X floatatom 171 33 5 0 0 0 - - -; +#X floatatom 171 88 0 0 0 0 - - -; +#X msg 236 33 bang; +#X floatatom 297 33 5 0 0 0 - - -; +#X floatatom 297 88 0 0 0 0 - - -; +#X obj 297 59 asin; +#X floatatom 101 139 5 0 0 0 - - -; +#X floatatom 101 194 0 0 0 0 - - -; +#X obj 101 165 cosh; +#X floatatom 230 139 5 0 0 0 - - -; +#X floatatom 230 194 0 0 0 0 - - -; +#X obj 230 165 sinh; +#X floatatom 366 139 5 0 0 0 - - -; +#X floatatom 366 194 0 0 0 0 - - -; +#X obj 366 165 tanh; +#X floatatom 40 320 5 0 0 0 - - -; +#X floatatom 40 405 0 0 0 0 - - -; +#X obj 40 346 cartopol; +#X floatatom 107 376 0 0 0 0 - - -; +#X floatatom 107 320 5 0 0 0 - - -; +#X floatatom 196 320 5 0 0 0 - - -; +#X floatatom 196 405 0 0 0 0 - - -; +#X floatatom 263 376 0 0 0 0 - - -; +#X floatatom 263 320 5 0 0 0 - - -; +#X obj 196 346 poltocar; +#X floatatom 346 320 5 0 0 0 - - -; +#X floatatom 346 405 0 0 0 0 - - -; +#X obj 346 346 cartopol; +#X floatatom 413 376 0 0 0 0 - - -; +#X floatatom 413 320 5 0 0 0 - - -; +#X obj 40 282 MouseState; +#X msg 40 253 poll; +#X msg 95 253 nopoll; +#X connect 0 0 2 0; +#X connect 1 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 6 0; +#X connect 6 0 5 0; +#X connect 7 0 9 0; +#X connect 9 0 8 0; +#X connect 10 0 12 0; +#X connect 12 0 11 0; +#X connect 13 0 15 0; +#X connect 15 0 14 0; +#X connect 16 0 18 0; +#X connect 18 0 17 0; +#X connect 18 0 25 0; +#X connect 18 1 19 0; +#X connect 18 1 25 1; +#X connect 20 0 18 1; +#X connect 21 0 25 0; +#X connect 24 0 25 1; +#X connect 25 0 22 0; +#X connect 25 0 28 0; +#X connect 25 1 23 0; +#X connect 25 1 28 1; +#X connect 26 0 28 0; +#X connect 28 0 27 0; +#X connect 28 1 29 0; +#X connect 30 0 28 1; +#X connect 31 1 16 0; +#X connect 31 2 20 0; +#X connect 32 0 31 0; +#X connect 33 0 31 0; diff --git a/test/cyclone/universal-test.pd b/test/cyclone/universal-test.pd new file mode 100644 index 0000000..a1b083d --- /dev/null +++ b/test/cyclone/universal-test.pd @@ -0,0 +1,55 @@ +#N canvas 329 126 483 198 12; +#X obj 25 60 universal; +#X msg 25 25 print bang; +#X obj 26 112 print one; +#X obj 27 152 print two; +#N canvas 0 0 384 238 sub 0; +#X obj 25 60 universal; +#X msg 25 25 print bang; +#X msg 159 25 print bang; +#X obj 159 60 universal 1; +#X obj 26 112 print sub-one; +#X obj 27 152 print sub-two; +#N canvas 0 0 390 231 sub-sub 0; +#X obj 25 60 universal; +#X msg 25 25 print bang; +#X msg 159 25 print bang; +#X obj 159 60 universal 1; +#X obj 26 112 print sub-sub-one; +#X obj 27 152 print sub-sub-two; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X restore 212 151 pd sub-sub; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X restore 163 152 pd sub; +#X msg 327 25 print bang; +#N canvas 0 0 384 238 zub 0; +#X obj 25 60 universal; +#X msg 25 25 print bang; +#X msg 159 25 print bang; +#X obj 159 60 universal 1; +#X obj 26 112 print zub-one; +#X obj 27 152 print zub-two; +#N canvas 0 0 390 231 zub-zub 0; +#X obj 25 60 universal; +#X msg 25 25 print bang; +#X msg 159 25 print bang; +#X obj 159 60 universal 1; +#X obj 26 112 print zub-zub-one; +#X obj 27 152 print zub-zub-two; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X restore 212 151 pd zub-zub; +#X connect 1 0 0 0; +#X connect 2 0 3 0; +#X restore 262 152 pd zub; +#X obj 327 60 universal 1; +#X msg 138 25 print; +#X msg 206 25 print list; +#X msg 137 74 list; +#X connect 1 0 0 0; +#X connect 5 0 7 0; +#X connect 8 0 0 0; +#X connect 9 0 0 0; +#X connect 10 0 2 0; diff --git a/test/cyclone/urn-test.pd b/test/cyclone/urn-test.pd new file mode 100644 index 0000000..ab2787d --- /dev/null +++ b/test/cyclone/urn-test.pd @@ -0,0 +1,15 @@ +#N canvas 433 476 450 300 12; +#X obj 152 131 urn 10; +#X obj 152 190 print; +#X msg 152 73 bang; +#X msg 220 73 clear; +#X msg 94 73 99; +#X msg 28 73 99.9; +#X msg 295 72 10000; +#X connect 0 0 1 0; +#X connect 0 1 1 0; +#X connect 2 0 0 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 0 0; +#X connect 6 0 0 1; diff --git a/test/cyclone/vectral-test.pd b/test/cyclone/vectral-test.pd new file mode 100644 index 0000000..dad2343 --- /dev/null +++ b/test/cyclone/vectral-test.pd @@ -0,0 +1,56 @@ +#N canvas 368 287 673 449 12; +#X obj 268 277 Scope~ 307 152 2 3 128 0 1 0 0 0 0 102 255 51 135 135 +135 0; +#X floatatom 303 111 5 0 0 0 - - -; +#X msg 404 171 2; +#X floatatom 404 200 5 0 0 0 - - -; +#X msg 503 226 bufsize \$1; +#X floatatom 503 200 5 0 0 0 - - -; +#X floatatom 18 80 5 0 0 0 - - -; +#X floatatom 80 80 5 0 0 0 - - -; +#X floatatom 370 111 5 0 0 0 - - -; +#X obj 303 137 sig~; +#X obj 18 106 sig~; +#X obj 80 106 sig~; +#X obj 370 137 phasor~ 0.5; +#X obj 267 227 vectral~ 256; +#X obj 9 15 block~ 256; +#X msg 503 171 128; +#X msg 404 226 range 0 1; +#X msg 23 180 slide \$1; +#X floatatom 23 154 5 0 0 0 - - -; +#X obj 267 54 count~ 0 256 1 1; +#X floatatom 27 221 5 0 0 0 - - -; +#X msg 27 345 deltaclip \$1 \$2; +#X obj 27 253 t 0 0; +#X obj 67 286 * -1; +#X obj 27 316 pack; +#X obj 303 86 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 +; +#X obj 24 406 capture~ 256; +#X connect 1 0 9 0; +#X connect 2 0 3 0; +#X connect 3 0 0 0; +#X connect 4 0 0 0; +#X connect 5 0 4 0; +#X connect 6 0 10 0; +#X connect 7 0 11 0; +#X connect 8 0 12 0; +#X connect 9 0 13 2; +#X connect 10 0 13 0; +#X connect 11 0 13 1; +#X connect 13 0 0 0; +#X connect 13 0 26 0; +#X connect 15 0 5 0; +#X connect 16 0 0 0; +#X connect 17 0 13 0; +#X connect 18 0 17 0; +#X connect 19 0 13 0; +#X connect 19 0 13 1; +#X connect 20 0 22 0; +#X connect 21 0 13 0; +#X connect 22 0 24 0; +#X connect 22 1 23 0; +#X connect 23 0 24 1; +#X connect 24 0 21 0; +#X connect 25 0 1 0; diff --git a/test/cyclone/xbend-test.pd b/test/cyclone/xbend-test.pd new file mode 100644 index 0000000..c7dcaa8 --- /dev/null +++ b/test/cyclone/xbend-test.pd @@ -0,0 +1,89 @@ +#N canvas 220 178 814 503 12; +#X msg 124 18 145 \, 0 \, 64; +#X msg 137 44 145 \, 1 \, 0; +#X floatatom 39 18 5 0 0; +#X msg 152 71 128 \, 2 \, 0; +#X msg 42 71 1 2 3; +#X msg 207 103 248; +#X msg 160 103 240; +#X obj 124 189 xbendin; +#X obj 124 225 funnel 2; +#X msg 198 143 224 \, 1 \, 2; +#X obj 247 189 xbendin 1; +#X obj 247 263 print single; +#X obj 124 263 print omni; +#X msg 311 143 225 \, 1 \, 2; +#X msg 499 18 145 \, 0 \, 64; +#X msg 512 44 145 \, 1 \, 0; +#X floatatom 414 18 5 0 0; +#X msg 527 71 128 \, 2 \, 0; +#X msg 417 71 1 2 3; +#X msg 582 103 248; +#X msg 535 103 240; +#X msg 573 143 224 \, 1 \, 2; +#X obj 622 263 print single; +#X obj 499 263 print omni; +#X msg 686 143 225 \, 1 \, 2; +#X obj 499 189 xbendin2; +#X obj 499 225 funnel 3; +#X obj 622 189 xbendin2 1; +#X obj 622 225 funnel 2; +#X obj 125 396 xbendout; +#X obj 125 442 print; +#X floatatom 125 327 5 0 0; +#X floatatom 192 358 5 0 0; +#X msg 50 358 bang; +#X obj 424 438 print; +#X floatatom 424 297 5 0 0; +#X floatatom 462 327 5 0 0; +#X msg 324 358 bang; +#X obj 424 392 xbendout2; +#X floatatom 500 358 5 0 0; +#X msg 360 327 1 2 3; +#X connect 0 0 7 0; +#X connect 1 0 7 0; +#X connect 2 0 7 0; +#X connect 2 0 10 0; +#X connect 3 0 7 0; +#X connect 4 0 7 0; +#X connect 4 0 10 0; +#X connect 5 0 7 0; +#X connect 6 0 7 0; +#X connect 7 0 8 0; +#X connect 7 1 8 1; +#X connect 8 0 12 0; +#X connect 9 0 7 0; +#X connect 9 0 10 0; +#X connect 10 0 11 0; +#X connect 13 0 7 0; +#X connect 13 0 10 0; +#X connect 14 0 25 0; +#X connect 15 0 25 0; +#X connect 16 0 25 0; +#X connect 16 0 27 0; +#X connect 17 0 25 0; +#X connect 18 0 25 0; +#X connect 18 0 27 0; +#X connect 19 0 25 0; +#X connect 20 0 25 0; +#X connect 21 0 25 0; +#X connect 21 0 27 0; +#X connect 24 0 25 0; +#X connect 24 0 27 0; +#X connect 25 0 26 0; +#X connect 25 1 26 1; +#X connect 25 2 26 2; +#X connect 26 0 23 0; +#X connect 27 0 28 0; +#X connect 27 1 28 1; +#X connect 28 0 22 0; +#X connect 29 0 30 0; +#X connect 31 0 29 0; +#X connect 32 0 29 1; +#X connect 33 0 29 0; +#X connect 35 0 38 0; +#X connect 36 0 38 1; +#X connect 37 0 38 0; +#X connect 38 0 34 0; +#X connect 39 0 38 2; +#X connect 40 0 38 0; diff --git a/test/cyclone/xnote-test.pd b/test/cyclone/xnote-test.pd new file mode 100644 index 0000000..8f9ac44 --- /dev/null +++ b/test/cyclone/xnote-test.pd @@ -0,0 +1,50 @@ +#N canvas 372 121 442 534 12; +#X msg 124 18 145 \, 0 \, 64; +#X msg 137 44 145 \, 1 \, 0; +#X floatatom 39 18 5 0 0; +#X msg 42 72 1 2 3; +#X msg 207 103 248; +#X msg 160 103 240; +#X msg 198 143 224 \, 1 \, 2; +#X obj 247 263 print single; +#X obj 124 263 print omni; +#X obj 116 482 print; +#X floatatom 116 317 5 0 0; +#X floatatom 138 341 5 0 0; +#X msg 41 367 bang; +#X obj 124 190 xnotein; +#X obj 124 225 funnel 4; +#X obj 247 225 funnel 3; +#X obj 247 190 xnotein 2; +#X msg 152 72 129 \, 2 \, 0; +#X obj 116 436 xnoteout; +#X floatatom 160 367 5 0 0; +#X floatatom 183 392 5 0 0; +#X connect 0 0 13 0; +#X connect 0 0 16 0; +#X connect 1 0 13 0; +#X connect 1 0 16 0; +#X connect 2 0 13 0; +#X connect 2 0 16 0; +#X connect 3 0 13 0; +#X connect 3 0 16 0; +#X connect 4 0 13 0; +#X connect 5 0 13 0; +#X connect 6 0 13 0; +#X connect 10 0 18 0; +#X connect 11 0 18 1; +#X connect 12 0 18 0; +#X connect 13 0 14 0; +#X connect 13 1 14 1; +#X connect 13 2 14 2; +#X connect 13 3 14 3; +#X connect 14 0 8 0; +#X connect 15 0 7 0; +#X connect 16 0 15 0; +#X connect 16 1 15 1; +#X connect 16 2 15 2; +#X connect 17 0 13 0; +#X connect 17 0 16 0; +#X connect 18 0 9 0; +#X connect 19 0 18 2; +#X connect 20 0 18 3; diff --git a/test/cyclone/zl-test.pd b/test/cyclone/zl-test.pd new file mode 100644 index 0000000..64900d0 --- /dev/null +++ b/test/cyclone/zl-test.pd @@ -0,0 +1,148 @@ +#N canvas 442 94 629 579 12; +#X msg 196 21 bang; +#X obj 196 161 zl group 3; +#X msg 296 21 a b c; +#X msg 62 133 symbol test; +#X floatatom 54 171 5 0 0 0 - - -; +#X msg 307 171 bang; +#X msg 308 105 symbol test; +#X floatatom 308 133 5 0 0 0 - - -; +#X msg 29 21 b c d e f; +#X msg 69 489 mode len \, debug \, bang \, mode previous \, debug; +#X msg 433 77 2nd; +#X msg 433 21 1st; +#X obj 433 105 testmess 150; +#X obj 433 49 testmess 150; +#X msg 69 517 mode reg \, debug \, bang \, mode previous \, debug; +#X msg 111 171 debug 1; +#X msg 54 77 -1 -2 -3 -4 -5; +#X msg 308 77 -4 -5 -6; +#X obj 524 237 zl; +#X msg 524 209 bang; +#X msg 462 209 debug; +#X msg 406 297 mode rev \, bang; +#X msg 487 21 set 1000; +#X msg 488 77 set 1000; +#X msg 406 353 mode union \, bang; +#X msg 406 325 mode sect \, bang; +#X floatatom 49 301 5 0 0 0 - - -; +#X msg 172 271 mode group \$1 \, bang; +#X floatatom 49 276 5 0 0 0 - - -; +#X msg 172 327 mode slice \$1 \, bang; +#X msg 406 381 mode join \, bang; +#X msg 172 243 mode iter \$1 \, bang; +#X floatatom 49 326 5 0 0 0 - - -; +#X floatatom 49 251 5 0 0 0 - - -; +#X msg 172 299 mode rot \$1 \, bang; +#X msg 172 355 mode ecils \$1 \, bang; +#X floatatom 49 351 5 0 0 0 - - -; +#X obj 196 189 print left; +#X obj 307 199 print right; +#X msg 172 383 mode nth \$1 \, bang; +#N canvas 0 0 450 300 prev 0; +#X obj 45 39 r doit; +#X obj 173 246 outlet; +#X obj 45 75 route mode; +#X obj 173 211 prepend mode; +#X obj 173 177 zl reg; +#X msg 173 143 bang; +#X obj 45 109 route len reg previous; +#X msg 92 177 debug 1; +#X connect 0 0 2 0; +#X connect 2 0 6 0; +#X connect 3 0 1 0; +#X connect 4 0 3 0; +#X connect 5 0 4 0; +#X connect 6 2 5 0; +#X connect 6 3 4 1; +#X connect 7 0 4 0; +#X restore 206 105 pd prev; +#X obj 41 549 s doit; +#X obj 359 458 s doit; +#X obj 196 133 r doit; +#X obj 409 133 s doit; +#X obj 104 458 s doit; +#X floatatom 49 382 5 0 0 0 - - -; +#X floatatom 49 407 5 0 0 0 - - -; +#X msg 172 411 mode nth \$1 x \, bang; +#X msg 406 409 mode sub \, bang; +#X obj 29 199 s doit; +#X msg 62 105 1 1 2 2 1 2; +#X msg 45 49 1 a b c test; +#X msg 259 49 1 2; +#X msg 308 49 148 149; +#X msg 487 133 bang; +#N canvas 419 256 450 300 more 0; +#X obj 118 117 zl sub; +#X obj 78 78 t a a; +#X obj 51 185 print upto; +#X obj 170 185 print downfrom; +#X msg 78 42 a list with a pattern to split upon; +#X msg 167 78 a pattern; +#X obj 51 150 zl slice; +#X msg 271 78 a list; +#X msg 351 78 upon; +#X msg 23 42 bang; +#X obj 23 78 t b b; +#X connect 0 0 6 1; +#X connect 1 0 6 0; +#X connect 1 1 0 0; +#X connect 4 0 1 0; +#X connect 5 0 0 1; +#X connect 6 0 2 0; +#X connect 6 1 3 0; +#X connect 7 0 0 1; +#X connect 8 0 0 1; +#X connect 9 0 10 0; +#X connect 10 0 6 0; +#X connect 10 1 0 0; +#X restore 396 251 pd more; +#X connect 0 0 1 0; +#X connect 1 0 37 0; +#X connect 1 1 38 0; +#X connect 2 0 1 1; +#X connect 3 0 50 0; +#X connect 4 0 50 0; +#X connect 5 0 1 1; +#X connect 6 0 1 1; +#X connect 7 0 1 1; +#X connect 8 0 50 0; +#X connect 9 0 41 0; +#X connect 10 0 12 0; +#X connect 11 0 13 0; +#X connect 12 0 1 1; +#X connect 13 0 44 0; +#X connect 14 0 41 0; +#X connect 15 0 1 0; +#X connect 16 0 50 0; +#X connect 17 0 1 1; +#X connect 19 0 18 0; +#X connect 20 0 18 0; +#X connect 21 0 42 0; +#X connect 22 0 13 0; +#X connect 23 0 12 0; +#X connect 24 0 42 0; +#X connect 25 0 42 0; +#X connect 26 0 34 0; +#X connect 27 0 45 0; +#X connect 28 0 27 0; +#X connect 29 0 45 0; +#X connect 30 0 42 0; +#X connect 31 0 45 0; +#X connect 32 0 29 0; +#X connect 33 0 31 0; +#X connect 34 0 45 0; +#X connect 35 0 45 0; +#X connect 36 0 35 0; +#X connect 39 0 45 0; +#X connect 40 0 1 0; +#X connect 43 0 1 0; +#X connect 46 0 39 0; +#X connect 47 0 48 0; +#X connect 48 0 45 0; +#X connect 49 0 42 0; +#X connect 51 0 50 0; +#X connect 52 0 50 0; +#X connect 53 0 1 1; +#X connect 54 0 1 1; +#X connect 55 0 12 0; |