fftease-2.5.2.git20121005/0000755000076500007650000000000012067452122013211 5ustar hanshansfftease-2.5.2.git20121005/LICENSE.txt0000644000076500007650000000245312067450034015040 0ustar hanshansThis software is released under the MIT License, as described here: http://www.opensource.org/licenses/mit-license.php and here: http://tinyurl.com/y6u53r -EL ******************************************************************* FFTease is Copyright (c) 1999-2008 Eric Lyon and Christopher Penrose Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. fftease-2.5.2.git20121005/MSPd.h0000644000076500007650000000130112067450034014160 0ustar hanshans#include #include #include #include /* choose your poison */ #define MSP (0) #define PD (!MSP) /* for compiling under XP */ #ifndef PIOVERTWO #define PIOVERTWO 1.5707963268 #define TWOPI 6.2831853072 #endif #if MSP #include "ext.h" #include "z_dsp.h" #include "buffer.h" #include "ext_obex.h" #define t_floatarg double #endif #if PD #include "m_pd.h" #define t_floatarg float #endif /* because Max and Pd have different ideas of what A_FLOAT is, use t_floatarg to force consistency. Otherwise functions that look good will fail on some hardware. Also note that Pd messages cannot accept arguments of type A_LONG. */ fftease-2.5.2.git20121005/Makefile0000644000076500007650000004166712067452034014671 0ustar hanshans## Pd library template version 1.0.13 # For instructions on how to use this template, see: # http://puredata.info/docs/developer/MakefileTemplate LIBRARY_NAME = fftease # add your .c source files, one object per file, to the SOURCES # variable, help files will be included automatically, and for GUI # objects, the matching .tcl file too SOURCES = bthresher~.c burrow~.c cavoc27~.c cavoc~.c centerring~.c codepend~.c crossx~.c dentist~.c disarrain~.c disarray~.c drown~.c ether~.c leaker~.c mindwarp~.c morphine~.c multyq~.c presidency~.c pvcompand~.c pvgrain~.c pvharm~.c pvoc~.c pvtuner~.c pvwarp~.c reanimator~.c resent~.c residency~.c scrape~.c shapee~.c swinger~.c taint~.c thresher~.c vacancy~.c xsyn~.c # list all pd objects (i.e. myobject.pd) files here, and their helpfiles will # be included automatically PDOBJECTS = ampdb.pd fftease-system.pd # example patches and related files, in the 'examples' subfolder EXAMPLES = 13et.scale 24et.scale 4th.scale blue3.scale m3chord.scale m3M3.scale octfifth.scale Piano.aif scale1.pl scale2.pl scale3.pl scale4.pl scale5.pl scale6.pl scale7.pl test.scale # manuals and related files, in the 'manual' subfolder MANUAL = code-notes.rtf # if you want to include any other files in the source and binary tarballs, # list them here. This can be anything from header files, test patches, # documentation, etc. README.txt and LICENSE.txt are required and therefore # automatically included EXTRA_DIST = fftease.h MSPd.h PenroseOscil.h PenroseRand.h pvtuner.h residency_buffer~.c # unit tests and related files here, in the 'unittests' subfolder UNITTESTS = # added to support the multiple shared source files SHARED_SOURCE = bloscbank.c convert.c fft4.c fft.c fftease_setup.c fold.c leanconvert.c leanunconvert.c limit_fftsize.c makewindows.c overlapadd.c PenroseOscil.c PenroseRand.c power_of_two.c qsortE.c unconvert.c SHARED_LIB = lib$(LIBRARY_NAME).$(SHARED_EXTENSION) #------------------------------------------------------------------------------# # # things you might need to edit if you are using other C libraries # #------------------------------------------------------------------------------# ALL_CFLAGS = -I"$(PD_INCLUDE)" ALL_LDFLAGS = SHARED_LDFLAGS = ALL_LIBS = #------------------------------------------------------------------------------# # # you shouldn't need to edit anything below here, if we did it right :) # #------------------------------------------------------------------------------# # these can be set from outside without (usually) breaking the build CFLAGS = -Wall -W -g LDFLAGS = LIBS = # get library version from meta file LIBRARY_VERSION = $(shell sed -n 's|^\#X text [0-9][0-9]* [0-9][0-9]* VERSION \(.*\);|\1|p' $(LIBRARY_NAME)-meta.pd) ALL_CFLAGS += -DPD -DVERSION='"$(LIBRARY_VERSION)"' PD_INCLUDE = $(PD_PATH)/include/pd # where to install the library, overridden below depending on platform prefix = /usr/local libdir = $(prefix)/lib pkglibdir = $(libdir)/pd-externals objectsdir = $(pkglibdir) INSTALL = install INSTALL_PROGRAM = $(INSTALL) -p -m 644 INSTALL_DATA = $(INSTALL) -p -m 644 INSTALL_DIR = $(INSTALL) -p -m 755 -d ALLSOURCES := $(SOURCES) $(SOURCES_android) $(SOURCES_cygwin) $(SOURCES_macosx) \ $(SOURCES_iphoneos) $(SOURCES_linux) $(SOURCES_windows) DISTDIR=$(LIBRARY_NAME)-$(LIBRARY_VERSION) ORIGDIR=pd-$(LIBRARY_NAME:~=)_$(LIBRARY_VERSION) UNAME := $(shell uname -s) ifeq ($(UNAME),Darwin) CPU := $(shell uname -p) ifeq ($(CPU),arm) # iPhone/iPod Touch SOURCES += $(SOURCES_iphoneos) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = iphoneos PD_PATH = /Applications/Pd-extended.app/Contents/Resources IPHONE_BASE=/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin CC=$(IPHONE_BASE)/gcc CPP=$(IPHONE_BASE)/cpp CXX=$(IPHONE_BASE)/g++ ISYSROOT = -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.0.sdk IPHONE_CFLAGS = -miphoneos-version-min=3.0 $(ISYSROOT) -arch armv6 OPT_CFLAGS = -fast -funroll-loops -fomit-frame-pointer ALL_CFLAGS := $(IPHONE_CFLAGS) $(ALL_CFLAGS) ALL_LDFLAGS += -arch armv6 -bundle -undefined dynamic_lookup $(ISYSROOT) SHARED_LDFLAGS += -arch armv6 -dynamiclib -undefined dynamic_lookup $(ISYSROOT) ALL_LIBS += -lc $(LIBS_iphoneos) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) else # Mac OS X SOURCES += $(SOURCES_macosx) EXTENSION = pd_darwin SHARED_EXTENSION = dylib OS = macosx PD_PATH = /Applications/Pd-extended.app/Contents/Resources OPT_CFLAGS = -ftree-vectorize -ftree-vectorizer-verbose=2 -fast # build universal 32-bit on 10.4 and 32/64 on newer ifeq ($(shell uname -r | sed 's|\([0-9][0-9]*\)\.[0-9][0-9]*\.[0-9][0-9]*|\1|'), 8) FAT_FLAGS = -arch ppc -arch i386 -mmacosx-version-min=10.4 else FAT_FLAGS = -arch ppc -arch i386 -arch x86_64 -mmacosx-version-min=10.4 SOURCES += $(SOURCES_iphoneos) endif ALL_CFLAGS += $(FAT_FLAGS) -fPIC -I/sw/include # if the 'pd' binary exists, check the linking against it to aid with stripping BUNDLE_LOADER = $(shell test ! -e $(PD_PATH)/bin/pd || echo -bundle_loader $(PD_PATH)/bin/pd) ALL_LDFLAGS += $(FAT_FLAGS) -headerpad_max_install_names -bundle $(BUNDLE_LOADER) \ -undefined dynamic_lookup -L/sw/lib SHARED_LDFLAGS += $(FAT_FLAGS) -dynamiclib -undefined dynamic_lookup \ -install_name @loader_path/$(SHARED_LIB) -compatibility_version 1 -current_version 1.0 ALL_LIBS += -lc $(LIBS_macosx) STRIP = strip -x DISTBINDIR=$(DISTDIR)-$(OS) # install into ~/Library/Pd on Mac OS X since /usr/local isn't used much pkglibdir=$(HOME)/Library/Pd endif endif # Tho Android uses Linux, we use this fake uname to provide an easy way to # setup all this things needed to cross-compile for Android using the NDK ifeq ($(UNAME),ANDROID) CPU := arm SOURCES += $(SOURCES_android) EXTENSION = pd_linux SHARED_EXTENSION = so OS = android PD_PATH = /usr NDK_BASE := /usr/local/android-ndk NDK_PLATFORM_VERSION := 5 NDK_SYSROOT=$(NDK_BASE)/platforms/android-$(NDK_PLATFORM_VERSION)/arch-arm NDK_UNAME := $(shell uname -s | tr '[A-Z]' '[a-z]') NDK_TOOLCHAIN_BASE=$(NDK_BASE)/toolchains/arm-linux-androideabi-4.4.3/prebuilt/$(NDK_UNAME)-x86 CC := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-gcc --sysroot=$(NDK_SYSROOT) OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer CFLAGS += LDFLAGS += -rdynamic -shared SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared LIBS += -lc $(LIBS_android) STRIP := $(NDK_TOOLCHAIN_BASE)/bin/arm-linux-androideabi-strip \ --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),Linux) CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -Wl,-soname,$(SHARED_LIB) -shared ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU) # GNU/Hurd, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq ($(UNAME),GNU/kFreeBSD) # Debian GNU/kFreeBSD, should work like GNU/Linux for basically all externals CPU := $(shell uname -m) SOURCES += $(SOURCES_linux) EXTENSION = pd_linux SHARED_EXTENSION = so OS = linux PD_PATH = /usr OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -fPIC ALL_LDFLAGS += -rdynamic -shared -fPIC -Wl,-rpath,"\$$ORIGIN",--enable-new-dtags SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc $(LIBS_linux) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS)-$(shell uname -m) endif ifeq (CYGWIN,$(findstring CYGWIN,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_cygwin) EXTENSION = dll SHARED_EXTENSION = dll OS = cygwin PD_PATH = $(shell cygpath $$PROGRAMFILES)/pd OPT_CFLAGS = -O6 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += ALL_LDFLAGS += -rdynamic -shared -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" SHARED_LDFLAGS += -shared -Wl,-soname,$(SHARED_LIB) ALL_LIBS += -lc -lpd $(LIBS_cygwin) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif ifeq (MINGW,$(findstring MINGW,$(UNAME))) CPU := $(shell uname -m) SOURCES += $(SOURCES_windows) EXTENSION = dll SHARED_EXTENSION = dll OS = windows PD_PATH = $(shell cd "$$PROGRAMFILES/pd" && pwd) # MinGW doesn't seem to include cc so force gcc CC=gcc OPT_CFLAGS = -O3 -funroll-loops -fomit-frame-pointer ALL_CFLAGS += -mms-bitfields ALL_LDFLAGS += -s -shared -Wl,--enable-auto-import SHARED_LDFLAGS += -shared ALL_LIBS += -L"$(PD_PATH)/src" -L"$(PD_PATH)/bin" -L"$(PD_PATH)/obj" \ -lpd -lwsock32 -lkernel32 -luser32 -lgdi32 -liberty $(LIBS_windows) STRIP = strip --strip-unneeded -R .note -R .comment DISTBINDIR=$(DISTDIR)-$(OS) endif # in case somebody manually set the HELPPATCHES above HELPPATCHES ?= $(SOURCES:.c=-help.pd) $(PDOBJECTS:.pd=-help.pd) ALL_CFLAGS := $(ALL_CFLAGS) $(CFLAGS) $(OPT_CFLAGS) ALL_LDFLAGS := $(LDFLAGS) $(ALL_LDFLAGS) ALL_LIBS := $(LIBS) $(ALL_LIBS) SHARED_SOURCE ?= $(wildcard lib$(LIBRARY_NAME).c) SHARED_HEADER ?= $(shell test ! -e $(LIBRARY_NAME).h || echo $(LIBRARY_NAME).h) SHARED_LIB ?= $(SHARED_SOURCE:.c=.$(SHARED_EXTENSION)) SHARED_TCL_LIB = $(wildcard lib$(LIBRARY_NAME).tcl) .PHONY = install libdir_install single_install install-doc install-examples install-manual install-unittests clean distclean dist etags $(LIBRARY_NAME) all: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) %.o: %.c $(CC) $(ALL_CFLAGS) -o "$*.o" -c "$*.c" %.$(EXTENSION): %.o $(SHARED_LIB) $(CC) $(ALL_LDFLAGS) -o "$*.$(EXTENSION)" "$*.o" $(ALL_LIBS) $(SHARED_LIB) chmod a-x "$*.$(EXTENSION)" # this links everything into a single binary file $(LIBRARY_NAME): $(SOURCES:.c=.o) $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(CC) $(ALL_LDFLAGS) -o $(LIBRARY_NAME).$(EXTENSION) $(SOURCES:.c=.o) \ $(LIBRARY_NAME).o lib$(LIBRARY_NAME).o $(ALL_LIBS) chmod a-x $(LIBRARY_NAME).$(EXTENSION) $(SHARED_LIB): $(SHARED_SOURCE:.c=.o) $(CC) $(SHARED_LDFLAGS) -o $(SHARED_LIB) $(SHARED_SOURCE:.c=.o) $(ALL_LIBS) install: libdir_install # The meta and help files are explicitly installed to make sure they are # actually there. Those files are not optional, then need to be there. libdir_install: $(SOURCES:.c=.$(EXTENSION)) $(SHARED_LIB) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES))" || (\ $(INSTALL_PROGRAM) $(SOURCES:.c=.$(EXTENSION)) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) && \ $(STRIP) $(addprefix $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/,$(SOURCES:.c=.$(EXTENSION)))) test -z "$(strip $(SHARED_LIB))" || \ $(INSTALL_DATA) $(SHARED_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(wildcard $(SOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(SOURCES:.c=.tcl)) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) # install library linked as single binary single_install: $(LIBRARY_NAME) install-doc install-examples install-manual install-unittests $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_PROGRAM) $(LIBRARY_NAME).$(EXTENSION) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(STRIP) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/$(LIBRARY_NAME).$(EXTENSION) install-doc: $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) test -z "$(strip $(SOURCES) $(PDOBJECTS))" || \ $(INSTALL_DATA) $(HELPPATCHES) \ $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME) $(INSTALL_DATA) README.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/README.txt $(INSTALL_DATA) LICENSE.txt $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/LICENSE.txt install-examples: test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/examples; \ done install-manual: test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/manual; \ done install-unittests: test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DESTDIR)$(objectsdir)/$(LIBRARY_NAME)/unittests; \ done clean: -rm -f -- $(SOURCES:.c=.o) $(SOURCES_LIB:.c=.o) $(SHARED_SOURCE:.c=.o) -rm -f -- $(SOURCES:.c=.$(EXTENSION)) -rm -f -- $(LIBRARY_NAME).o -rm -f -- $(LIBRARY_NAME).$(EXTENSION) -rm -f -- $(SHARED_LIB) distclean: clean -rm -f -- $(DISTBINDIR).tar.gz -rm -rf -- $(DISTBINDIR) -rm -f -- $(DISTDIR).tar.gz -rm -rf -- $(DISTDIR) -rm -f -- $(ORIGDIR).tar.gz -rm -rf -- $(ORIGDIR) $(DISTBINDIR): $(INSTALL_DIR) $(DISTBINDIR) libdir: all $(DISTBINDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTBINDIR) $(INSTALL_DATA) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) $(DISTBINDIR) $(INSTALL_DATA) $(HELPPATCHES) $(DISTBINDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTBINDIR) # tar --exclude-vcs -czpf $(DISTBINDIR).tar.gz $(DISTBINDIR) $(DISTDIR): $(INSTALL_DIR) $(DISTDIR) $(ORIGDIR): $(INSTALL_DIR) $(ORIGDIR) dist: $(DISTDIR) $(INSTALL_DATA) Makefile $(DISTDIR) $(INSTALL_DATA) README.txt $(DISTDIR) $(INSTALL_DATA) LICENSE.txt $(DISTDIR) $(INSTALL_DATA) $(LIBRARY_NAME)-meta.pd $(DISTDIR) test -z "$(strip $(ALLSOURCES))" || \ $(INSTALL_DATA) $(ALLSOURCES) $(DISTDIR) test -z "$(strip $(wildcard $(ALLSOURCES:.c=.tcl)))" || \ $(INSTALL_DATA) $(wildcard $(ALLSOURCES:.c=.tcl)) $(DISTDIR) test -z "$(strip $(wildcard $(LIBRARY_NAME).c))" || \ $(INSTALL_DATA) $(LIBRARY_NAME).c $(DISTDIR) test -z "$(strip $(SHARED_HEADER))" || \ $(INSTALL_DATA) $(SHARED_HEADER) $(DISTDIR) test -z "$(strip $(SHARED_SOURCE))" || \ $(INSTALL_DATA) $(SHARED_SOURCE) $(DISTDIR) test -z "$(strip $(SHARED_TCL_LIB))" || \ $(INSTALL_DATA) $(SHARED_TCL_LIB) $(DISTDIR) test -z "$(strip $(PDOBJECTS))" || \ $(INSTALL_DATA) $(PDOBJECTS) $(DISTDIR) test -z "$(strip $(HELPPATCHES))" || \ $(INSTALL_DATA) $(HELPPATCHES) $(DISTDIR) test -z "$(strip $(EXTRA_DIST))" || \ $(INSTALL_DATA) $(EXTRA_DIST) $(DISTDIR) test -z "$(strip $(EXAMPLES))" || \ $(INSTALL_DIR) $(DISTDIR)/examples && \ for file in $(EXAMPLES); do \ $(INSTALL_DATA) examples/$$file $(DISTDIR)/examples; \ done test -z "$(strip $(MANUAL))" || \ $(INSTALL_DIR) $(DISTDIR)/manual && \ for file in $(MANUAL); do \ $(INSTALL_DATA) manual/$$file $(DISTDIR)/manual; \ done test -z "$(strip $(UNITTESTS))" || \ $(INSTALL_DIR) $(DISTDIR)/unittests && \ for file in $(UNITTESTS); do \ $(INSTALL_DATA) unittests/$$file $(DISTDIR)/unittests; \ done tar --exclude-vcs -czpf $(DISTDIR).tar.gz $(DISTDIR) # make a Debian source package dpkg-source: debclean make distclean dist mv $(DISTDIR) $(ORIGDIR) tar --exclude-vcs -czpf ../$(ORIGDIR).orig.tar.gz $(ORIGDIR) rm -f -- $(DISTDIR).tar.gz rm -rf -- $(DISTDIR) $(ORIGDIR) cd .. && dpkg-source -b $(LIBRARY_NAME) etags: TAGS TAGS: $(wildcard $(PD_INCLUDE)/*.h) $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags $(wildcard $(PD_INCLUDE)/*.h) etags -a *.h $(SOURCES) $(SHARED_SOURCE) $(SHARED_HEADER) etags -a --language=none --regex="/proc[ \t]+\([^ \t]+\)/\1/" *.tcl showsetup: @echo "CC: $(CC)" @echo "CFLAGS: $(CFLAGS)" @echo "LDFLAGS: $(LDFLAGS)" @echo "LIBS: $(LIBS)" @echo "ALL_CFLAGS: $(ALL_CFLAGS)" @echo "ALL_LDFLAGS: $(ALL_LDFLAGS)" @echo "ALL_LIBS: $(ALL_LIBS)" @echo "PD_INCLUDE: $(PD_INCLUDE)" @echo "PD_PATH: $(PD_PATH)" @echo "objectsdir: $(objectsdir)" @echo "LIBRARY_NAME: $(LIBRARY_NAME)" @echo "LIBRARY_VERSION: $(LIBRARY_VERSION)" @echo "SOURCES: $(SOURCES)" @echo "SHARED_HEADER: $(SHARED_HEADER)" @echo "SHARED_SOURCE: $(SHARED_SOURCE)" @echo "SHARED_LIB: $(SHARED_LIB)" @echo "SHARED_TCL_LIB: $(SHARED_TCL_LIB)" @echo "PDOBJECTS: $(PDOBJECTS)" @echo "ALLSOURCES: $(ALLSOURCES)" @echo "ALLSOURCES TCL: $(wildcard $(ALLSOURCES:.c=.tcl))" @echo "UNAME: $(UNAME)" @echo "CPU: $(CPU)" @echo "pkglibdir: $(pkglibdir)" @echo "DISTDIR: $(DISTDIR)" @echo "ORIGDIR: $(ORIGDIR)" fftease-2.5.2.git20121005/PenroseOscil.c0000644000076500007650000000135712067450034015770 0ustar hanshans#include #include "PenroseOscil.h" float frequencyToIncrement( float samplingRate, float frequency, int bufferLength ) { return (frequency / samplingRate) * (float) bufferLength; } void makeSineBuffer( float *buffer, int bufferLength ) { int i; float myTwoPi = 8. * atan(1.); for ( i=0; i <= bufferLength; i++ ) *(buffer+i) = sin( myTwoPi * ((float) i / (float) bufferLength) ); return; } float bufferOscil( float *phase, float increment, float *buffer, int bufferLength ) { float sample; while ( *phase > bufferLength ) *phase -= bufferLength; while ( *phase < 0. ) *phase += bufferLength; sample = *( buffer + (int) (*phase) ); *phase += increment; return sample; } fftease-2.5.2.git20121005/PenroseOscil.h0000644000076500007650000000037712067450034015776 0ustar hanshans float frequencyToIncrement( float samplingRate, float frequency, int bufferLength ); void makeSineBuffer( float *buffer, int bufferLength ); float bufferOscil( float *phase, float increment, float *buffer, int bufferLength ); fftease-2.5.2.git20121005/PenroseRand.c0000644000076500007650000000042212067450034015573 0ustar hanshans#include "PenroseRand.h" float rrand(int *seed) { int i = ((*seed = *seed * 1103515245 + 12345)>>16) & 077777; return((float)i/16384. - 1.); } float prand(int *seed) { int i = ((*seed = *seed * 1103515245 + 12345)>>16) & 077777; return((float)i/32768.); } fftease-2.5.2.git20121005/PenroseRand.h0000644000076500007650000000006112067450034015577 0ustar hanshans float rrand(int *seed); float prand(int *seed); fftease-2.5.2.git20121005/README.txt0000644000076500007650000000417212067450034014713 0ustar hanshansFFTease 2.5 by Eric Lyon and Christopher Penrose This is the third release of FFTease, a set of live spectral sound processors for Max/MSP and Pd. This Pd distribution is compiled for Linux, OS X, and Windows. Move the appropriate set of binaries from "bin" to the Pd "extra" folder. Move the contents of "help" to the Pd "doc/5.reference" directory. You are now ready to use FFTease. Caveat: these objects are CPU intensive. A few of these objects in a patch could push your computer to its limits. Be very careful with playback volume as some of the objects produce dramatically different (lower or higher) overall levels. The FFT size, which must be a power of 2, is calculated relative to the Pd block size. It is recommended to use FFTease externals in a sub-patch that contains a block~ object, granting you control of the local block size, and thus FFT size. A larger block size results in a larger FFT size. Don't expect a great savings in CPU usage with smaller block sizes. But do expect increased CPU load as you crank the block size up. A block size of 256, with a default overlap of 4 gives an FFT size of 1024 that works acceptably well in many cases. With some of these objects, an even smaller block size/FFT size can actually work better. See the abstraction "fftease-system.pd" for more information on how to control these parameters. Acknowledgements: This work draws heavily on the phase vocoder code presented by F. Richard Moore in his classic "Elements of Computer Music." Additional inspiration was derived from work on cross synthesis and noise reduction by Mark Dolson at CARL in the mid-1980s. We also wish to thank Miller Puckette and David Zicarelli for designing and implementing the framework under which FFTease is presented. The authors would like to warmly acknowledge the support of the following institutions: Brown University, Dartmouth College, IAMAS, Keio University, the University of Manchester, and Queen's University Belfast. FFTease is copyright 2000-2009 Eric Lyon and Christopher Penrose. FFTease is released under the MIT license. Eric Lyon e.lyon@qub.ac.uk Christopher Penrose penrose@silvertone.princeton.edu fftease-2.5.2.git20121005/ampdb-help.pd0000644000076500007650000000066212067452034015555 0ustar hanshans#N canvas 111 157 450 300 10; #X obj 102 144 ampdb; #X floatatom 102 119 5 0 0 0 - - -; #X obj 105 94 hsl 128 15 -150 0 0 0 empty empty empty -2 -8 0 10 -262144 -1 -1 0 1; #X floatatom 102 178 10 0 0 0 - - -; #X text 46 49 convert negative decibels (dB) to amplitude between 0 and 1; #X text 166 117 input range is roughly -150 to 0; #X text 179 178 output range is 0 to 1; #X connect 0 0 3 0; #X connect 1 0 0 0; #X connect 2 0 1 0; fftease-2.5.2.git20121005/ampdb.pd0000644000076500007650000000062512067450034014624 0ustar hanshans#N canvas 945 219 212 299 10; #X obj 32 107 pow; #X obj 32 64 t b f; #X msg 32 83 10; #X obj 54 170 /; #X obj 32 127 t b f; #X msg 32 148 1; #X obj 32 41 * -0.05; #X obj 32 19 inlet; #X obj 54 193 outlet; #X connect 0 0 4 0; #X connect 1 0 2 0; #X connect 1 1 0 1; #X connect 2 0 0 0; #X connect 3 0 8 0; #X connect 4 0 5 0; #X connect 4 1 3 1; #X connect 5 0 3 0; #X connect 6 0 1 0; #X connect 7 0 6 0; fftease-2.5.2.git20121005/bloscbank.c0000644000076500007650000000140112067450034015307 0ustar hanshans #include "fftease.h" void bloscbank( float *S, float *O, int D, float iD, float *lf, float *la, float *index, float *tab, int len, float synt, int lo, int hi ) { int amp,freq,chan, i; float a,ainc,f,finc,address; for ( chan = lo; chan < hi; chan++ ) { freq = ( amp = ( chan << 1 ) ) + 1; if ( S[amp] > synt ){ finc = ( S[freq] - ( f = lf[chan] ) )* iD; ainc = ( S[amp] - ( a = la[chan] ) )* iD; address = index[chan]; for ( i = 0; i < D ; i++ ) { O[i] += a*tab[ (int) address ]; address += f; while ( address >= len ) address -= len; while ( address < 0 ) address += len; a += ainc; f += finc; } lf[chan] = S[freq]; la[chan] = S[amp]; index[chan] = address; } } }fftease-2.5.2.git20121005/bthresher~-help.pd0000644000076500007650000001577212067450034016664 0ustar hanshans#N canvas 609 64 625 468 10; #N canvas 0 22 478 328 bthresher-block 0; #X obj 177 189 block~ 256; #X obj 188 161 outlet~; #X obj 344 173 outlet; #X obj 188 40 inlet~; #X obj 266 65 inlet; #X obj 344 69 inlet; #X obj 391 101 inlet; #X obj 188 117 bthresher~ 0.1 0.97 4 1; #X connect 3 0 7 0; #X connect 4 0 7 1; #X connect 5 0 7 2; #X connect 6 0 7 0; #X connect 7 0 1 0; #X connect 7 1 2 0; #X restore 154 133 pd bthresher-block; #X obj 154 206 dac~; #X obj 154 34 noise~; #N canvas 613 44 522 372 messages 0; #X obj 32 248 outlet; #N canvas 314 293 617 400 individual-bin-control 0; #X obj 23 363 outlet; #X obj 220 97 pack f f f; #X floatatom 220 48 5 0 0 1 bin_number - -; #X floatatom 252 62 5 0 0 1 damping_factor - -; #X floatatom 285 78 5 0 0 1 threshold - -; #X text 23 29 format:; #X msg 153 241 0 0.968693 0.124173 1 0.968693 0.124173 2 0.968693 0.124173 3 0.968693 0.124173 4 0.968693 0.124173 5 0.93 0.01 6 0.93 0.01 7 0.93 0.01 8 0.93 0.01 9 0.93 0.01 10 0.93 0.01 11 0.93 0.01 12 0.93 0.1 13 0.93 0.1 14 0.93 0.1 15 0.93 0.1 16 0.93 0.1 17 0.968693 0.124173 18 0.968693 0.124173 19 0.968693 0.124173 20 0.968693 0.124173; #X msg 23 56 bin 5 0.93 0.01; #X text 23 41 bin # \, damping \, threshold; #X msg 220 139 bin \$1 \$2 \$3; #X text 153 223 or send raw data controlling many bins from a list ; #X text 23 17 affect a single bin; #X text 219 31 construct bin message from components; #X connect 1 0 9 0; #X connect 2 0 1 0; #X connect 3 0 1 1; #X connect 4 0 1 2; #X connect 6 0 0 0; #X connect 7 0 0 0; #X connect 9 0 0 0; #X restore 32 20 pd individual-bin-control; #N canvas 0 22 498 348 global-bin-control 0; #X msg 253 203 alldamp \$1; #X msg 221 105 allthresh \$1; #X floatatom 221 73 5 0 0 0 - allthresh -; #X floatatom 253 181 5 0 0 0 - alldamp -; #X obj 221 238 outlet; #X obj 62 90 vsl 15 128 0 0.2 0 0 allthresh allthresh-init allthresh 0 -8 0 8 -117632 -1 -1 6985 1; #X obj 117 90 vsl 15 128 0 1.1 0 0 alldamp alldamp-init alldamp 0 -8 0 8 -117632 -1 -1 11084 1; #X connect 0 0 4 0; #X connect 1 0 4 0; #X connect 2 0 1 0; #X connect 3 0 0 0; #X restore 69 113 pd global-bin-control; #N canvas 0 22 494 344 random-bin-control 0; #X obj 8 105 outlet; #X text 4 33 format: min max; #X msg 8 50 rthreshold 0.05 0.7; #X msg 149 49 rdamper 0.8 0.999; #X connect 2 0 0 0; #X connect 3 0 0 0; #X restore 60 78 pd random-bin-control; #X text 222 21 <- start here; #N canvas 444 60 502 352 system 0; #X obj 26 268 outlet; #X text 122 87 arg must be power of 2; #X obj 26 19 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 26 43 mute \$1; #X msg 124 103 overlap 4; #X msg 124 122 overlap 2; #X text 193 124 <- cuts CPU demand in half; #X text 197 105 <- default; #X msg 134 252 fftinfo; #X msg 140 185 winfac 1; #X text 136 166 relative size of input window to FFT; #X msg 210 186 winfac 2; #X connect 2 0 3 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 8 0 0 0; #X connect 9 0 0 0; #X connect 11 0 0 0; #X restore 83 158 pd system; #X msg 197 189 dump; #X text 195 172 with a list message; #X text 195 145 output current state; #X text 196 159 which can then be reloaded; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X restore 275 97 pd messages; #X msg 79 242 \; pd dsp \$1; #X obj 79 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X obj 154 163 *~ 0.2; #X floatatom 194 70 5 0 0 0 - scale-thresh -; #X floatatom 234 95 5 0 0 0 - scale-damping -; #X obj 191 268 hsl 128 15 0 2 0 0 scale-thresh slider-init scale-thresh -2 -6 0 8 -258369 -1 -1 6350 1; #X obj 191 302 hsl 128 15 0 2 0 0 scale-damping slider-init scale-damping -2 -6 0 8 -258369 -1 -1 6350 1; #N canvas 137 230 511 492 capture 0; #X obj 8 12 inlet; #X text 20 173 clear; #X msg 8 237 0 0.960032 0.11 1 0.960032 0.11 2 0.960032 0.11 3 0.960032 0.11 4 0.960032 0.11 5 0.960032 0.11 6 0.960032 0.11 7 0.960032 0.11 8 0.960032 0.11 9 0.960032 0.11 10 0.960032 0.11 11 0.960032 0.11 12 0.960032 0.11 13 0.960032 0.11 14 0.960032 0.11 15 0.960032 0.11 16 0.960032 0.11 17 0.960032 0.11 18 0.960032 0.11 19 0.960032 0.11 0 0.838661 0.383391 1 0.85394 0.349312 2 0.963181 0.277742 3 0.863287 0.111771 4 0.871333 0.331876 5 0.940383 0.510999 6 0.94973 0.125378 7 0.992569 0.100742 8 0.80563 0.290001 9 0.943857 0.0718399 10 0.971641 0.17489 11 0.928632 0.356374 12 0.871212 0.144183 13 0.933891 0.516592 14 0.918071 0.480113 15 0.851894 0.330705 16 0.97568 0.339909 17 0.98587 0.380415 18 0.859807 0.39325 19 0.839784 0.422369 0 0.838661 0.383391 1 0.85394 0.349312 2 0.963181 0.277742 3 0.863287 0.111771 4 0.871333 0.331876 5 0.940383 0.510999 6 0.94973 0.125378 7 0.992569 0.100742 8 0.80563 0.290001 9 0.943857 0.0718399 10 0.971641 0.17489 11 0.928632 0.356374 12 0.871212 0.144183 13 0.933891 0.516592 14 0.918071 0.480113 15 0.851894 0.330705 16 0.97568 0.339909 17 0.98587 0.380415 18 0.859807 0.39325 19 0.839784 0.422369; #X msg 23 191 set; #X text 82 15 capture (some) list output from 'dump' message; #X msg 8 59 add2 \$1 \$2 \$3 \$4 \$5 \$6 \$7 \$8 \$9 \$10 \$11 \$12 \$13 \$14 \$15 \$16 \$17 \$18 \$19 \$20 \$21 \$22 \$23 \$24 \$25 \$26 \$27 \$28 \$29 \$30 \$31 \$32 \$33 \$34 \$35 \$36 \$37 \$38 \$39 \$40 \$41 \$42 \$43 \$44 \$45 \$46 \$47 \$48 \$49 \$50 \$51 \$52 \$53 \$54 \$55 \$56 \$57 \$58 \$59 \$60; #X text 86 118 The "dump" message outputs the current state of bthresher~ as a series of triplets [bin# \, damp factor \, threshold]. This data can be captured as a list and reloaded to itself or any other bthresher~ unit. In this example we only show the first twenty triplets. Since there are potentially as many as N/2 triplets where N is the FFT size \, you would need to modify this subpatch to capture all the information of the current state of bthresher~. (A version of Pd with the "prepend" object would make your life easier here.); #X connect 0 0 5 0; #X connect 3 0 2 0; #X connect 5 0 2 0; #X restore 275 159 pd capture; #N canvas 0 22 470 320 initialize 0; #X obj 38 150 s slider-init; #X msg 38 85 1; #X obj 38 51 loadbang; #X obj 142 150 s allthresh-init; #X obj 265 150 s alldamp-init; #X msg 265 83 0.96; #X msg 142 83 0.11; #X obj 142 41 inlet; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 2 0 6 0; #X connect 2 0 5 0; #X connect 5 0 4 0; #X connect 6 0 3 0; #X connect 7 0 1 0; #X connect 7 0 6 0; #X connect 7 0 5 0; #X restore 399 270 pd initialize; #X text 364 97 <- click me to learn more; #X obj 399 245 loadbang; #X text 50 336 bthresher~ extends the thresher~ model to allow independent control over the parameters of each individual bin. You can also randomly set damping and threshold values \, and can dump the current values (to possibly send as input to another bthresher~ unit). It is recommended that you familiarize yourself with thresher~ before exploring the more complicated bthresher~.; #X text 182 52 threshold scale factor; #X text 237 80 damping scale factor; #X text 351 160 <- state captured here; #X connect 0 0 6 0; #X connect 0 1 11 0; #X connect 2 0 0 0; #X connect 3 0 0 3; #X connect 5 0 4 0; #X connect 6 0 1 0; #X connect 6 0 1 1; #X connect 7 0 0 1; #X connect 8 0 0 2; #X connect 14 0 12 0; fftease-2.5.2.git20121005/bthresher~.c0000644000076500007650000004237512067450034015554 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *bthresher_class; #endif #if PD static t_class *bthresher_class; #endif #define OBJECT_NAME "bthresher~" typedef struct _bthresher { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int in_count; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; /* bthresher vars */ float *move_threshold; float *composite_frame ; int *frames_left; int max_hold_frames; float max_hold_time; int first_frame; float *damping_factor ; float thresh_scalar; float damp_scalar; short thresh_connected; short damping_connected; void *list_outlet; void *misc_outlet; t_atom *list_data; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // for fast fft float mult; float *trigland; int *bitshuffle; short mute; short bypass; float init_thresh; float init_damping; int overlap; int winfac; float tadv; short inf_hold; } t_bthresher; void *bthresher_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *bthresher_perform(t_int *w); void bthresher_dsp(t_bthresher *x, t_signal **sp, short *count); void bthresher_assist(t_bthresher *x, void *b, long m, long a, char *s); void bthresher_float(t_bthresher *x, double f); void bthresher_mute(t_bthresher *x, t_floatarg f); void bthresher_bypass(t_bthresher *x, t_floatarg f); void bthresher_overlap(t_bthresher *x, t_floatarg f); void bthresher_winfac(t_bthresher *x, t_floatarg f); void bthresher_fftinfo(t_bthresher *x); void bthresher_free(t_bthresher *x); void bthresher_bin(t_bthresher *x, t_floatarg bin_num, t_floatarg threshold, t_floatarg damper); void bthresher_rdamper(t_bthresher *x, t_floatarg min, t_floatarg max ); void bthresher_rthreshold(t_bthresher *x, t_floatarg min, t_floatarg max); void bthresher_dump(t_bthresher *x ); void bthresher_list (t_bthresher *x, t_symbol *msg, short argc, t_atom *argv); void bthresher_init(t_bthresher *x, short initialized); float bthresher_boundrand(float min, float max); void bthresher_allthresh(t_bthresher *x, t_floatarg f); void bthresher_alldamp(t_bthresher *x, t_floatarg f); void bthresher_inf_hold(t_bthresher *x, t_floatarg f); void bthresher_max_hold(t_bthresher *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&bthresher_class, (method)bthresher_new, (method)bthresher_free, (short)sizeof(t_bthresher), 0, A_GIMME, 0); addmess((method)bthresher_dsp, "dsp", A_CANT, 0); addmess((method)bthresher_assist,"assist",A_CANT,0); addmess((method)bthresher_mute,"mute",A_FLOAT,0); addmess((method)bthresher_bypass,"bypass",A_FLOAT,0); addmess((method)bthresher_overlap,"overlap",A_FLOAT,0); addmess((method)bthresher_winfac,"winfac",A_FLOAT,0); addmess((method)bthresher_fftinfo,"fftinfo",0); addmess ((method)bthresher_bin, "bin", A_FLOAT, A_FLOAT, A_FLOAT, 0); addmess ((method)bthresher_rdamper, "rdamper", A_DEFFLOAT, A_DEFFLOAT, 0); addmess ((method)bthresher_rthreshold, "rthreshold", A_DEFFLOAT, A_DEFFLOAT, 0); addmess((method)bthresher_dump,"dump",0); addmess((method)bthresher_list,"list",A_GIMME,0); addmess((method)bthresher_alldamp,"alldamp",A_FLOAT,0); addmess((method)bthresher_allthresh,"allthresh",A_FLOAT,0); addmess((method)bthresher_inf_hold,"inf_hold",A_FLOAT,0); addmess((method)bthresher_max_hold,"max_hold",A_FLOAT,0); addfloat((method)bthresher_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void bthresher_tilde_setup(void){ bthresher_class = class_new(gensym("bthresher~"), (t_newmethod)bthresher_new, (t_method)bthresher_free ,sizeof(t_bthresher), 0,A_GIMME,0); CLASS_MAINSIGNALIN(bthresher_class, t_bthresher, x_f); class_addmethod(bthresher_class,(t_method)bthresher_dsp,gensym("dsp"),0); class_addmethod(bthresher_class,(t_method)bthresher_mute,gensym("mute"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_bypass,gensym("bypass"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_fftinfo,gensym("fftinfo"),0); class_addmethod(bthresher_class,(t_method)bthresher_rdamper,gensym("rdamper"),A_FLOAT,A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_rthreshold,gensym("rthreshold"),A_FLOAT,A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_dump,gensym("dump"),0); class_addmethod(bthresher_class,(t_method)bthresher_list,gensym("list"),A_GIMME,0); class_addmethod(bthresher_class,(t_method)bthresher_alldamp,gensym("alldamp"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_allthresh,gensym("allthresh"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_inf_hold,gensym("inf_hold"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_max_hold,gensym("max_hold"),A_FLOAT,0); class_addmethod(bthresher_class,(t_method)bthresher_bin,gensym("bin"),A_FLOAT,A_FLOAT,A_FLOAT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void bthresher_fftinfo( t_bthresher *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void bthresher_free( t_bthresher *x ){ #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->input,0); freebytes(x->output,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); /* full phase vocoder */ freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); /* external-specific memory */ freebytes(x->composite_frame,0); freebytes(x->frames_left,0); freebytes(x->move_threshold,0); freebytes(x->damping_factor,0); freebytes(x->list_data,0); } void bthresher_max_hold(t_bthresher *x, t_floatarg f) { if(f<=0) return; x->max_hold_time = f * .001; x->max_hold_frames = x->max_hold_time / x->tadv; } void bthresher_inf_hold(t_bthresher *x, t_floatarg f) { x->inf_hold = (int)f; } void bthresher_allthresh(t_bthresher *x, t_floatarg f) { int i; //post("thresh %f",f); for(i=0;iN2+1;i++) x->move_threshold[i] = f; } void bthresher_alldamp(t_bthresher *x, t_floatarg f) { int i; //post("damp %f",f); for(i=0;iN2+1;i++) x->damping_factor[i] = f; } void bthresher_overlap(t_bthresher *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; bthresher_init(x,1); } void bthresher_winfac(t_bthresher *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; bthresher_init(x,2); } void bthresher_mute(t_bthresher *x, t_floatarg f){ x->mute = f; } void bthresher_bypass(t_bthresher *x, t_floatarg f){ x->bypass = f; } void bthresher_assist (t_bthresher *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0:sprintf(dst,"(signal) Input");break; case 1:sprintf(dst,"(signal/float) Threshold Scalar");break; case 2:sprintf(dst,"(signal/float) Damping Factor Scalar");break; } } else if (msg==2) { switch (arg) { case 0:sprintf(dst,"(signal) Output");break; case 1:sprintf(dst,"(list) Current State");break; } } } void bthresher_list (t_bthresher *x, t_symbol *msg, short argc, t_atom *argv) { int i, bin, idiv; float fdiv; float *damping_factor = x->damping_factor; float *move_threshold = x->move_threshold; // post("reading %d elements", argc); idiv = fdiv = (float) argc / 3.0 ; if( fdiv - idiv > 0.0 ) { post("list must be in triplets"); return; } /* for( i = 0; i < x->N2+1; i++) { move_threshold[i] = 0.0 ; }*/ for( i = 0; i < argc; i += 3 ) { bin = atom_getintarg(i,argc,argv); damping_factor[bin] = atom_getfloatarg(i+1,argc,argv); move_threshold[bin] = atom_getfloatarg(i+2,argc,argv); /* bin = argv[i].a_w.w_long ; damping_factor[bin] = argv[i + 1].a_w.w_float; move_threshold[bin] = argv[i + 2].a_w.w_float;*/ } } void bthresher_dump (t_bthresher *x) { t_atom *list_data = x->list_data; float *damping_factor = x->damping_factor; float *move_threshold = x->move_threshold; int i,j, count; #if MSP for( i = 0, j = 0; i < x->N2 * 3 ; i += 3, j++ ) { SETLONG(list_data+i,j); SETFLOAT(list_data+(i+1),damping_factor[j]); SETFLOAT(list_data+(i+2),move_threshold[j]); } #endif #if PD for( i = 0, j = 0; i < x->N2 * 3 ; i += 3, j++ ) { SETFLOAT(list_data+i,(float)j); SETFLOAT(list_data+(i+1),damping_factor[j]); SETFLOAT(list_data+(i+2),move_threshold[j]); } #endif count = x->N2 * 3; outlet_list(x->list_outlet,0,count,list_data); return; } void *bthresher_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_bthresher *x = (t_bthresher *)newobject(bthresher_class); x->list_outlet = listout((t_pxobject *)x); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_bthresher *x = (t_bthresher *)pd_new(bthresher_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); x->list_outlet = outlet_new(&x->x_obj,gensym("list")); #endif x->D = sys_getblksize(); x->R = sys_getsr(); x->init_thresh = atom_getfloatarg(0,argc,argv); x->init_damping = atom_getfloatarg(1,argc,argv); x->overlap = atom_getintarg(2,argc,argv); x->winfac = atom_getintarg(3,argc,argv); bthresher_init(x,0); return (x); } void bthresher_init(t_bthresher *x, short initialized) { int i; if(!x->D) x->D = 256; if(!x->R) x->R = 44100; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->mult = 1. / (float) x->N; x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->in_count = -(x->Nw); x->c_fundamental = (float) x->R/((x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->first_frame = 1; x->max_hold_time = 60.0 ; x->thresh_connected = 0; x->damping_connected = 0; x->thresh_scalar = 1; x->damp_scalar = 1; x->mute = 0; x->bypass = 0; x->inf_hold = 0; x->Wanal = (float *) getbytes((MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes((MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes((MAX_Nw) * sizeof(float)); x->input = (float *) getbytes((MAX_Nw) * sizeof(float)); x->buffer = (float *) getbytes((MAX_N) * sizeof(float)); x->channel = (float *) getbytes(((MAX_N+2)) * sizeof(float)); x->output = (float *) getbytes((MAX_Nw) * sizeof(float)); x->bitshuffle = (int *) getbytes((MAX_N * 2) * sizeof(int)); x->trigland = (float *) getbytes((MAX_N * 2) * sizeof(float)); x->c_lastphase_in = (float *) getbytes((MAX_N2+1)* sizeof(float)); x->c_lastphase_out = (float *) getbytes((MAX_N2+1)* sizeof(float)); x->composite_frame = (float *) getbytes( (MAX_N+2)* sizeof(float)); x->frames_left = (int *) getbytes((MAX_N+2)* sizeof(int)); // TRIPLETS OF bin# damp_factor threshold x->list_data = (t_atom *) getbytes((MAX_N2 + 1) * 3 * sizeof(t_atom)); x->move_threshold = (float *) getbytes((MAX_N2+1)* sizeof(float)); x->damping_factor = (float *) getbytes((MAX_N2+1)* sizeof(float)); } if(initialized == 0 || initialized == 1){ for(i = 0; i < x->N2+1; i++) { x->move_threshold[i] = x->init_thresh; x->damping_factor[i] = x->init_damping; } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); x->tadv = (float) x->D / (float) x->R; x->max_hold_frames = x->max_hold_time / x->tadv; init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } void bthresher_rdamper(t_bthresher *x, t_floatarg min, t_floatarg max) { int i; for( i = 0; i < x->N2; i++ ) { x->damping_factor[i] = bthresher_boundrand(min, max); } } void bthresher_rthreshold( t_bthresher *x, t_floatarg min, t_floatarg max ) { int i; for( i = 0; i < x->N2; i++ ) { x->move_threshold[i] = bthresher_boundrand(min, max); } } void bthresher_bin(t_bthresher *x, t_floatarg bin_num, t_floatarg damper, t_floatarg threshold) { int bn = (int) bin_num; if( bn >= 0 && bn < x->N2 ){ // post("setting %d to %f %f",bn,threshold,damper); x->move_threshold[bn] = threshold; x->damping_factor[bn] = damper; } else { post("bthresher~: %d is out of range", bn); } } t_int *bthresher_perform(t_int *w) { float sample, outsamp ; int i, j, on; t_bthresher *x = (t_bthresher *) (w[1]); float *in = (t_float *)(w[2]); float *inthresh = (t_float *)(w[3]); float *damping = (t_float *)(w[4]); float *out = (t_float *)(w[5]); t_int n = w[6]; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; int in_count = x->in_count; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *damping_factor = x->damping_factor; float *move_threshold = x->move_threshold; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float *composite_frame = x->composite_frame; int max_hold_frames = x->max_hold_frames; int *frames_left = x->frames_left; float thresh_scalar = x->thresh_scalar; float damp_scalar = x->damp_scalar; short inf_hold = x->inf_hold; if( x->mute ) { for( j = 0; j < D; j++) { *out++ = 0.0 ; } } else if ( x->bypass ) { for( j = 0; j < D; j++) { *out++ = *in++ * 0.5; } } else { #if MSP if( x->thresh_connected ) { thresh_scalar = *inthresh++; } if( x->damping_connected ) { damp_scalar = *damping++; } #endif #if PD thresh_scalar = *inthresh++; damp_scalar = *damping++; #endif in_count += D; for ( j = 0 ; j < Nw - D ; j++ ) input[j] = input[j+D]; for ( j = Nw-D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, in_count ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, x->c_lastphase_in, x->c_fundamental, x->c_factor_in ); if( x->first_frame ){ for ( i = 0; i < N+2; i++ ){ composite_frame[i] = channel[i]; x->frames_left[i] = max_hold_frames; } x->first_frame = 0; } else { if( thresh_scalar < .999 || thresh_scalar > 1.001 || damp_scalar < .999 || damp_scalar > 1.001 ) { for(i = 0, j = 0; i < N+2; i += 2, j++ ){ if( fabs( composite_frame[i] - channel[i] ) > move_threshold[j] * thresh_scalar|| frames_left[j] <= 0 ){ composite_frame[i] = channel[i]; composite_frame[i+1] = channel[i+1]; frames_left[j] = max_hold_frames; } else { if(!inf_hold){ --(frames_left[j]); } composite_frame[i] *= damping_factor[j] * damp_scalar; } } } else { for( i = 0, j = 0; i < N+2; i += 2, j++ ){ if( fabs( composite_frame[i] - channel[i] ) > move_threshold[j] || frames_left[j] <= 0 ){ composite_frame[i] = channel[i]; composite_frame[i+1] = channel[i+1]; frames_left[j] = max_hold_frames; } else { if(!inf_hold){ --(frames_left[j]); } composite_frame[i] *= damping_factor[j]; } } } } unconvert(x->composite_frame, buffer, N2, x->c_lastphase_out, x->c_fundamental, x->c_factor_out); rdft(N, -1, buffer, bitshuffle, trigland); overlapadd(buffer, N, Wsyn, output, Nw, in_count); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; } x->in_count = in_count % Nw; x->thresh_scalar = thresh_scalar; x->damp_scalar = damp_scalar; return (w+7); } #if MSP void bthresher_float(t_bthresher *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; int i; if (inlet == 1) { x->thresh_scalar = f; } else if (inlet == 2) { x->damp_scalar = f; } } #endif void bthresher_dsp(t_bthresher *x, t_signal **sp, short *count) { #if MSP x->thresh_connected = count[1]; x->damping_connected = count[2]; #endif if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; bthresher_init(x,1); } dsp_add(bthresher_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } float bthresher_boundrand( float min, float max) { float frand; frand = (float) (rand() % 32768)/ 32768.0; return (min + frand * (max-min) ); } fftease-2.5.2.git20121005/burrow~-help.pd0000644000076500007650000000772712067450034016217 0ustar hanshans#N canvas 579 109 517 612 10; #N canvas 590 312 458 308 burrow-block 0; #X obj 160 154 burrow~; #X obj 160 39 inlet~; #X obj 174 72 inlet~; #X obj 189 99 inlet; #X obj 204 120 inlet; #X obj 160 209 outlet~; #X obj 270 186 block~ 256; #X obj 303 124 inlet; #X connect 0 0 5 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 7 0 0 0; #X restore 93 227 pd burrow-block; #X obj 93 42 noise~; #X obj 118 82 noise~; #X obj 118 129 bp~ 500 50; #X text 90 25 sound to filter; #X text 115 66 sound to provide filter shape; #X obj 93 269 *~ 1; #X obj 93 304 dac~; #X msg 352 411 \; pd dsp \$1; #X obj 352 394 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X floatatom 116 251 5 0 0 0 - burrow-gain -; #X obj 151 313 hsl 128 15 0 0.2 0 0 burrow-gain empty output_gain -2 -6 0 8 -182539 -1 -1 3175 1; #X floatatom 143 150 5 0 0 0 - burrow-threshold -; #X floatatom 168 170 5 0 0 0 - burrow-multiplier -; #N canvas 0 22 505 427 messages 0; #X obj 162 351 outlet; #X msg 162 253 invert \$1; #X obj 162 227 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 59 49 When invert is turned on \, the spectrum of the filter sound becomes the shape of the filter. Although this might seem more intuitive \, and thus a better candidate for default behavior \, recall that the external is called "burrow~" which is what it does.; #N canvas 380 158 454 304 system 0; #X obj 201 186 outlet; #X msg 93 128 overlap \$1; #X msg 84 96 2; #X msg 118 96 4; #X obj 298 44 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 298 70 mute \$1; #X msg 302 132 fftinfo; #X msg 145 47 2; #X msg 179 47 4; #X msg 154 79 winfac \$1; #X msg 109 46 1; #X text 25 235 Try different combos of window factor and overlap. Lower overlap requires less CPU.; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 1 0; #X connect 4 0 5 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 7 0 9 0; #X connect 8 0 9 0; #X connect 9 0 0 0; #X connect 10 0 9 0; #X restore 182 305 pd system; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 4 0 0 0; #X restore 193 197 pd messages; #X obj 153 348 hsl 128 15 0.0001 0.01 0 0 burrow-threshold empty threshold -2 -6 0 8 -182539 -1 -1 3720 1; #X obj 154 381 hsl 128 15 0.001 1 0 0 burrow-multiplier empty multiplier -2 -6 0 8 -182539 -1 -1 114 1; #X floatatom 150 103 5 0 0 0 - bp-center-freq -; #X obj 154 412 hsl 128 15 100 1500 0 0 bp-center-freq empty center-freq -2 -6 0 8 -182539 -1 -1 8164 1; #X floatatom 205 103 5 0 0 0 - bp-resonance -; #X obj 153 442 hsl 128 15 10 100 0 0 bp-resonance empty resonance -2 -6 0 8 -182539 -1 -1 12700 1; #X text 12 476 The sound in the leftmost inlet gets filtered by the spectrum of the sound in the next inlet \, except that by default this spectrum is cut out from (or burrows into) the source sound. We use noise sources here to highlight the effect but it is recommended to use much more interesting sounds as one or both of the inputs. In this example \, with bandpassed noise as the filter sound \, the result is to create a notch in the source noise \, similar but inverse to the shape of the bandpass peak band.; #N canvas 0 22 462 312 init 0; #X obj 92 140 unpack f f f f f; #X obj 92 95 loadbang; #X obj 92 195 outlet; #X obj 110 234 outlet; #X obj 131 276 outlet; #X obj 165 256 outlet; #X obj 213 246 outlet; #X obj 197 71 inlet; #X msg 92 117 0.05 0.003 0.01 100 1000; #X connect 0 0 2 0; #X connect 0 1 3 0; #X connect 0 2 4 0; #X connect 0 3 5 0; #X connect 0 4 6 0; #X connect 1 0 8 0; #X connect 7 0 8 0; #X connect 8 0 0 0; #X restore 94 381 pd init; #X obj 94 364 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X connect 0 0 6 0; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 0 1; #X connect 6 0 7 0; #X connect 6 0 7 1; #X connect 9 0 8 0; #X connect 10 0 6 1; #X connect 12 0 0 2; #X connect 13 0 0 3; #X connect 14 0 0 4; #X connect 17 0 3 1; #X connect 19 0 3 2; #X connect 22 0 11 0; #X connect 22 1 15 0; #X connect 22 2 16 0; #X connect 22 3 20 0; #X connect 22 4 18 0; #X connect 23 0 22 0; fftease-2.5.2.git20121005/burrow~.c0000644000076500007650000003254312067450034015102 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *burrow_class; #endif #if PD static t_class *burrow_class; #endif #define OBJECT_NAME "burrow~" /* after adding fixes, window factors > 1 are defective. Is there a remaining bug, or is this a problem for FFT-only processors? */ /* A few changes: Threshold and Multiplier now have their own inlets, which accept (signal/float). The input is now linear, rather than in dB. Reasons for this: 1) Linear input is the Max/MSP convention 2) It is easy to convert from linear to dB in Max 3) (My favorite) This cuts down on programmer overhead. */ typedef struct _burrow { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int invert; int *bitshuffle; float threshold; float multiplier; float mult; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_burrow; /* msp function prototypes */ void *burrow_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *burrow_perform(t_int *w); void burrow_dsp(t_burrow *x, t_signal **sp, short *count); void burrow_assist(t_burrow *x, void *b, long m, long a, char *s); void burrow_float(t_burrow *x, t_floatarg myFloat); void burrow_init(t_burrow *x, short initialized); void burrow_free(t_burrow *x); void burrow_invert(t_burrow *x, t_floatarg toggle); void burrow_mute(t_burrow *x, t_floatarg toggle); void burrow_fftinfo(t_burrow *x); void burrow_tilde_setup(void); void burrow_overlap(t_burrow *x, t_floatarg o); void burrow_winfac(t_burrow *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&burrow_class,(method) burrow_new, (method)burrow_free, (short) sizeof(t_burrow),0, A_GIMME, 0); addmess((method)burrow_dsp, "dsp", A_CANT, 0); addmess((method)burrow_assist,"assist",A_CANT,0); addmess((method)burrow_invert,"invert", A_FLOAT, 0); addmess((method)burrow_overlap,"overlap", A_FLOAT, 0); addmess((method)burrow_mute,"mute", A_FLOAT, 0); addmess((method)burrow_winfac,"winfac",A_FLOAT,0); addmess((method)burrow_fftinfo,"fftinfo", 0); addfloat((method)burrow_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } /* float input handling routines (MSP only) */ void burrow_float(t_burrow *x, t_floatarg myFloat) { int inlet = ((t_pxobject*)x)->z_in; if ( inlet == 2 ) // added two outlets so position is moved over x->threshold = myFloat; if ( inlet == 3 ) x->multiplier = myFloat; } #endif #if PD void burrow_tilde_setup(void) { burrow_class = class_new(gensym("burrow~"), (t_newmethod)burrow_new, (t_method)burrow_free ,sizeof(t_burrow), 0,A_GIMME,0); CLASS_MAINSIGNALIN(burrow_class, t_burrow, x_f); class_addmethod(burrow_class, (t_method)burrow_dsp, gensym("dsp"), 0); class_addmethod(burrow_class, (t_method)burrow_assist, gensym("assist"), 0); class_addmethod(burrow_class, (t_method)burrow_invert, gensym("invert"), A_FLOAT,0); class_addmethod(burrow_class, (t_method)burrow_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(burrow_class, (t_method)burrow_mute, gensym("mute"), A_FLOAT,0); class_addmethod(burrow_class, (t_method)burrow_fftinfo, gensym("fftinfo"), A_CANT,0); class_addmethod(burrow_class,(t_method)burrow_winfac,gensym("winfac"),A_FLOAT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void burrow_free(t_burrow *x) { #if MSP dsp_free((t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->Hwin); free(x->inputOne); free(x->inputTwo); free(x->bufferOne); free(x->bufferTwo); free(x->channelOne); free(x->channelTwo); free(x->output); } void burrow_invert(t_burrow *x, t_floatarg toggle) { x->invert = toggle; } void burrow_mute(t_burrow *x, t_floatarg toggle) { x->mute = toggle; } void burrow_overlap(t_burrow *x, t_floatarg o) { if(!fftease_power_of_two(o)){ error("%f is not a power of two",o); return; } x->overlap = o; burrow_init(x,1); } void burrow_winfac(t_burrow *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; burrow_init(x,1); } void burrow_fftinfo( t_burrow *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } /* diagnostic messages for Max */ void burrow_assist (t_burrow *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Source Sound"); break; case 1: sprintf(dst,"(signal) Burrow Filtering Sound"); break; case 2: sprintf(dst,"(signal/float) Filter Threshold"); break; case 3: sprintf(dst,"(signal/float) Filter Multiplier"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void burrow_init(t_burrow *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->invert = 0; x->inputOne = (float *) calloc(MAX_Nw, sizeof(float)); x->inputTwo = (float *) calloc(MAX_Nw, sizeof(float)); x->bufferOne = (float *) calloc(MAX_N, sizeof(float)); x->bufferTwo = (float *) calloc(MAX_N, sizeof(float)); x->channelOne = (float *) calloc((MAX_N+2), sizeof(float)); x->channelTwo = (float *) calloc((MAX_N+2), sizeof(float)); x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->bufferOne,0,x->N * sizeof(float)); memset((char *)x->bufferTwo,0,x->N * sizeof(float)); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); init_rdft( x->N, x->bitshuffle, x->trigland); } void *burrow_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_burrow *x = (t_burrow *) newobject(burrow_class); dsp_setup((t_pxobject *)x,4); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_burrow *x = (t_burrow *)pd_new(burrow_class); /* add three additional signal inlets */ inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: threshold, multiplier, overlap, winfac */ x->threshold = atom_getfloatarg(0,argc,argv); x->multiplier = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } if(x->threshold > 1.0 || x->threshold < 0.0){ x->threshold = 0; } if(x->multiplier > 1.0 || x->multiplier < 0.0){ x->multiplier = .01; } x->vs = sys_getblksize(); x->R = sys_getsr(); burrow_init(x,0); return(x); } t_int *burrow_perform(t_int *w) { /* get our inlets and outlets */ t_burrow *x = (t_burrow *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *flt_threshold = (t_float *)(w[4]); t_float *flt_multiplier = (t_float *)(w[5]); t_float *out = (t_float *)(w[6]); t_int n = w[7]; short *connected = x->connected; int i,j, inCount, R, N, N2, D, Nw, invert = 0, even, odd, *bitshuffle; float maxamp, threshold = 1., multiplier = 1., mult, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; /* dereference structure */ inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; multiplier = x->multiplier; threshold = x->threshold; mult = x->mult; invert = x->invert; if(connected[2]){ threshold = *flt_threshold; } else { threshold = x->threshold; } if(connected[3]){ multiplier = *flt_multiplier; } else { multiplier = x->multiplier; } /* save some CPUs if muted */ if(x->mute){ while(n--) *out++ = 0.0; return (w+8); } /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw-D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* use redundant coding for speed, even though moving the invert variable comparison outside of the for loop will give us only a minimal performance increase (hypot and atan2 are the most intensive portions of this code). consider adding a table lookup for atan2 instead. */ if (invert) { /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); /* use simple threshold from second signal to trigger filtering */ if ( *(channelTwo+even) < threshold ) *(channelOne+even) *= multiplier; /* *(channelTwo+odd) = -atan2( b2, a2 ); */ } } else { /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); /* use simple threshold from second signal to trigger filtering */ if ( *(channelTwo+even) > threshold ) *(channelOne+even) *= multiplier; /* *(channelTwo+odd) = -atan2( b2, a2 ); */ } } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+8); } void burrow_dsp(t_burrow *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 4; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 4; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; burrow_init(x,1); } dsp_add(burrow_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/cavoc27~-help.pd0000644000076500007650000000476712067450034016144 0ustar hanshans#N canvas 323 304 466 316 10; #N canvas 0 22 462 312 cavoc27-block 0; #X obj 141 110 cavoc27~ 0.05 200 4 1; #X obj 141 61 inlet~; #X obj 141 156 outlet~; #X obj 255 78 inlet; #X obj 142 212 block~ 256; #X text 89 187 args: density \, holdtime \, overlap \, winfac; #X connect 0 0 2 0; #X connect 1 0 0 0; #X connect 3 0 0 0; #X restore 146 109 pd cavoc27-block; #N canvas 0 22 478 328 messages 0; #X obj 111 220 outlet; #N canvas 0 22 466 316 rules 0; #X obj 15 181 outlet; #X msg 2 36 rule 1 0 1 0 0 0 1 0 0 1 2 1 0 2 0 2 0 0 1 0 2 0 2 1 2 1 1; #X msg 9 58 rule 0 2 1 0 0 1 0 0 0 1 1 2 0 1 2 1 1 1 1 0 0 0 1 1 0 1 1; #X msg 28 88 rule 2 2 0 1 0 2 1 1 0 2 1 2 0 1 1 2 0 2 2 1 2 1 1 2 0 0 0; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X restore 111 134 pd rules; #N canvas 520 382 466 316 messages 0; #X obj 59 290 outlet; #X msg 308 110 interpolate \$1; #X obj 308 87 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X msg 199 241 hold_time \$1; #X floatatom 199 212 5 0 0 0 - - -; #X floatatom 305 211 5 0 0 0 - - -; #X msg 305 242 density \$1; #X msg 61 37 retune 0.5 2; #X obj 89 68 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X msg 89 92 capture_spectrum \$1; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 0 0; #X connect 4 0 3 0; #X connect 5 0 6 0; #X connect 6 0 0 0; #X connect 7 0 0 0; #X connect 8 0 9 0; #X connect 9 0 0 0; #X restore 180 134 pd messages; #X obj 273 135 fftease-system; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X restore 253 81 pd messages; #X obj 146 208 dac~; #X msg 287 201 \; pd dsp \$1; #X obj 287 176 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 200 147 hsl 128 15 0 0.01 0 0 empty empty output_gain -2 -6 0 10 -245150 -1 -1 0 1; #N canvas 0 22 462 312 example-input-spectrum 0; #X obj 114 228 outlet~; #X obj 62 124 phasor~ 100; #X obj 145 124 phasor~ 125; #X obj 231 125 phasor~ 150; #X obj 114 175 *~ 0.333; #X text 26 89 this gets sampled when "capture_spectrum" is on; #X connect 1 0 4 0; #X connect 2 0 4 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X restore 146 48 pd example-input-spectrum; #X text 341 82 <- info; #X floatatom 197 168 5 0 0 0 - - -; #X obj 146 185 *~ 0.001; #X text 21 256 27 rule cellular automata (CA). New rules lists have 27 values (0 \, 1 \, or 2). Start with VERY low gain. See cavoc~ for a simpler implementation of CA-generated spectra.; #X connect 0 0 9 0; #X connect 1 0 0 1; #X connect 4 0 3 0; #X connect 5 0 8 0; #X connect 6 0 0 0; #X connect 8 0 9 1; #X connect 9 0 2 0; #X connect 9 0 2 1; fftease-2.5.2.git20121005/cavoc27~.c0000644000076500007650000004431212067450034015023 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *cavoc27_class; #endif #if PD static t_class *cavoc27_class; #endif #define OBJECT_NAME "cavoc27~" /* NOTE THIS IS A MORE COMPLEX CA WITH 3 DIFFERENT STATES */ typedef struct _cavoc27 { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *ichannel; //for interpolation float *tmpchannel; // for spectrum capture float *output; float frame_duration; int max_bin; // for CAVOC2 float fundamental; float *last_frame; short left; short right; short center; short *rule; float density; float start_breakpoint; int hold_frames; int frames_left; int set_count; short interpolate_flag; short capture_flag; short capture_lock; // FFT // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; float mult; float *trigland; int *bitshuffle; // void *list_outlet; t_atom *list_data; short mute; int winfac;//window factor int overlap;//overlap factor int vs;//vector size float hold_time;//hold time in seconds } t_cavoc27; void *cavoc27_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *cavoc27_perform(t_int *w); void cavoc27_dsp(t_cavoc27 *x, t_signal **sp, short *count); void cavoc27_assist(t_cavoc27 *x, void *b, long m, long a, char *s); void cavoc27_free( t_cavoc27 *x); int cavoc27_apply_rule( short left, short right, short center, short *rule); float cavoc27_randf(float min, float max); void cavoc27_rule (t_cavoc27 *x, t_symbol *msg, short argc, t_atom *argv); void cavoc27_density (t_cavoc27 *x, t_floatarg density); void cavoc27_hold_time (t_cavoc27 *x, t_floatarg hold_time); void cavoc27_interpolate (t_cavoc27 *x, t_floatarg interpolate); void cavoc27_capture_spectrum (t_cavoc27 *x, t_floatarg flag ); void cavoc27_capture_lock (t_cavoc27 *x, t_floatarg toggle ); void cavoc27_retune (t_cavoc27 *x, t_floatarg min, t_floatarg max); void cavoc27_mute (t_cavoc27 *x, t_floatarg toggle); void cavoc27_init(t_cavoc27 *x,short initialized); void cavoc27_rand_set_spectrum(t_cavoc27 *x); void cavoc27_rand_set_rule(t_cavoc27 *x); void cavoc27_fftinfo(t_cavoc27 *x); void cavoc27_overlap(t_cavoc27 *x, t_floatarg f); void cavoc27_winfac(t_cavoc27 *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&cavoc27_class, (method)cavoc27_new, (method)cavoc27_free, (short)sizeof(t_cavoc27), 0, A_GIMME, 0); addmess((method)cavoc27_dsp, "dsp", A_CANT, 0); addmess((method)cavoc27_assist,"assist",A_CANT,0); addmess((method)cavoc27_rule,"rule",A_GIMME,0); addmess((method)cavoc27_density,"density",A_FLOAT,0); addmess((method)cavoc27_hold_time,"hold_time",A_FLOAT,0); addmess((method)cavoc27_interpolate,"interpolate",A_FLOAT,0); addmess((method)cavoc27_overlap,"overlap",A_FLOAT,0); addmess((method)cavoc27_winfac,"winfac",A_FLOAT,0); addmess((method)cavoc27_fftinfo,"fftinfo",0); addmess((method)cavoc27_retune,"retune",A_FLOAT,A_FLOAT,0); addmess((method)cavoc27_capture_spectrum,"capture_spectrum",A_FLOAT,0); addmess((method)cavoc27_mute,"mute",A_FLOAT,0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD /* Pd Initialization */ void cavoc27_tilde_setup(void) { cavoc27_class = class_new(gensym("cavoc27~"), (t_newmethod)cavoc27_new, (t_method)cavoc27_free ,sizeof(t_cavoc27), 0,A_GIMME,0); CLASS_MAINSIGNALIN(cavoc27_class, t_cavoc27, x_f); class_addmethod(cavoc27_class, (t_method)cavoc27_dsp, gensym("dsp"), 0); class_addmethod(cavoc27_class, (t_method)cavoc27_mute, gensym("mute"), A_FLOAT,0); class_addmethod(cavoc27_class, (t_method)cavoc27_rule, gensym("rule"), A_GIMME,0); class_addmethod(cavoc27_class, (t_method)cavoc27_density, gensym("density"), A_DEFFLOAT,0); class_addmethod(cavoc27_class, (t_method)cavoc27_hold_time, gensym("hold_time"), A_DEFFLOAT,0); class_addmethod(cavoc27_class, (t_method)cavoc27_interpolate, gensym("interpolate"), A_DEFFLOAT, 0); class_addmethod(cavoc27_class, (t_method)cavoc27_capture_spectrum, gensym("capture_spectrum"), A_FLOAT, 0); class_addmethod(cavoc27_class, (t_method)cavoc27_retune, gensym("retune"), A_DEFFLOAT,A_DEFFLOAT,0); class_addmethod(cavoc27_class, (t_method)cavoc27_overlap, gensym("overlap"), A_FLOAT, 0); class_addmethod(cavoc27_class, (t_method)cavoc27_winfac, gensym("winfac"), A_FLOAT, 0); class_addmethod(cavoc27_class, (t_method)cavoc27_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void cavoc27_rand_set_rule(t_cavoc27 *x) { int i; float rval; for( i = 0; i < 27; i++ ){ rval = cavoc27_randf(0.0,1.0); if( rval < .333 ) x->rule[i] = 0; else if(rval < .666 ) x->rule[i] = 1; else x->rule[i] = 2; } } void cavoc27_retune(t_cavoc27 *x, t_floatarg min, t_floatarg max) { int i; if( max <= 0 || min <= 0 || min > max ){ error("bad values for min and max multipliers"); return; } if( min < .1 ) min = 0.1; if( max > 2.0 ) max = 2.0; for( i = 0; i < x->N2 + 1; i++ ){ x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc27_randf(min, max); } } void cavoc27_density(t_cavoc27 *x, t_floatarg density) { int i; if( density < 0.0001 ){ density = .0001; } else if( density > .9999 ){ density = 1.0; } x->density = density; x->start_breakpoint = 1.0 - x->density; for( i = 0; i < x->N2 + 1; i++ ){ if( cavoc27_randf(0.0, 1.0) > x->start_breakpoint ){ if( cavoc27_randf(0.0,1.0) > 0.5 ){ x->channel[ i * 2 ] = 1; } else { x->channel[ i * 2 ] = 2; } ++(x->set_count); } else { x->channel[ i * 2 ] = 0; } } for( i = 0; i < x->N+2; i++ ){ x->last_frame[i] = x->channel[i]; } } void cavoc27_mute (t_cavoc27 *x, t_floatarg toggle) { x->mute = (short)toggle; } void cavoc27_hold_time(t_cavoc27 *x, t_floatarg hold_time) { if(hold_time <= 0){ post("illegal hold time %f",hold_time); return; } x->hold_time = hold_time; if(! x->frame_duration){ error("%s: zero frame duration",OBJECT_NAME); x->frame_duration = .15; } x->hold_frames = (int) ( (hold_time/1000.0) / x->frame_duration); if( x->hold_frames < 1 ) x->hold_frames = 1; // x->frames_left = x->hold_frames; } void cavoc27_interpolate(t_cavoc27 *x, t_floatarg flag) { x->interpolate_flag = (short) flag; } void cavoc27_capture_spectrum(t_cavoc27 *x, t_floatarg flag ) { // now identical to capture_lock x->capture_lock = (short)flag; } void cavoc27_capture_lock(t_cavoc27 *x, t_floatarg flag ) { x->capture_lock = (short)flag; } void cavoc27_rule (t_cavoc27 *x, t_symbol *msg, short argc, t_atom *argv) { int i; short *rule = x->rule; if( argc != 27 ){ error("the rule must be size 18"); return; } for( i = 0; i < 27; i++ ){ rule[i] = (short) atom_getfloatarg( i, argc, argv); } } void cavoc27_free( t_cavoc27 *x ){ #if MSP dsp_free( (t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->input); free(x->Hwin); free(x->buffer); free(x->channel); free(x->ichannel); free(x->tmpchannel); free(x->last_frame); free(x->output); free(x->c_lastphase_out); free(x->rule); } void cavoc27_assist (t_cavoc27 *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"unused(signal)"); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"output(signal)"); break; } } } void *cavoc27_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_cavoc27 *x = (t_cavoc27 *)newobject(cavoc27_class); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); #endif #if PD int i; t_cavoc27 *x = (t_cavoc27 *)pd_new(cavoc27_class); outlet_new(&x->x_obj, gensym("signal")); #endif x->overlap = 0; x->winfac=0; x->hold_time=0; x->density = 0; x->density = atom_getfloatarg(0,argc,argv); x->hold_time = atom_getfloatarg(1,argc,argv) * .001;// convert to seconds x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(x->density <= 0) x->density = .0001; if(x->density >= 1) x->density = .9999; x->start_breakpoint = 1.0 - x->density; if(!x->hold_time) x->hold_time = 0.15; x->vs = sys_getblksize(); x->R = sys_getsr(); cavoc27_init(x,0); return (x); } void cavoc27_overlap(t_cavoc27 *x, t_floatarg f) { int i = (int) f; if(!power_of_two(i)){ post("%f is not a power of two",f); return; } x->overlap = i; cavoc27_init(x,1); } void cavoc27_winfac(t_cavoc27 *x, t_floatarg f) { int i = (int)f; if(!power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; cavoc27_init(x,2); } void cavoc27_fftinfo(t_cavoc27 *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void cavoc27_init(t_cavoc27 *x,short initialized) { int i; if(!power_of_two(x->overlap)) x->overlap = 4; if(!power_of_two(x->winfac)) x->winfac = 1; //post("init with o %d and wf %d",x->overlap,x->winfac); x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->frame_duration = (float)x->D/(float) x->R; x->hold_frames = (int) (x->hold_time/x->frame_duration); x->frames_left = x->hold_frames; // x->frames_left = 0; x->set_count = 0; if(!initialized){ srand(time(0)); x->interpolate_flag = 0; x->capture_lock = 0; x->mute = 0; x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->input = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->buffer = (float *) calloc(MAX_N, sizeof(float)); x->channel = (float *) calloc(MAX_N+2, sizeof(float)); x->ichannel = (float *) calloc(MAX_N+2, sizeof(float)); x->tmpchannel = (float *) calloc(MAX_N+2, sizeof(float)); x->rule = (short *) calloc(27, sizeof(short)); x->last_frame = (float *) calloc(MAX_N+2, sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); x->c_lastphase_in = (float *) calloc(MAX_N2+1, sizeof(float)); x->c_lastphase_out = (float *) calloc(MAX_N2+1, sizeof(float)); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); cavoc27_rand_set_rule(x); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); cavoc27_rand_set_spectrum(x); for( i = 0; i < x->N+2; i++ ){ x->last_frame[i] = x->channel[i]; } } void cavoc27_rand_set_spectrum(t_cavoc27 *x) { int i; float rval; //set spectrum for( i = 0; i < x->N2 + 1; i++ ){ if( cavoc27_randf(0.0, 1.0) > x->start_breakpoint){ rval = cavoc27_randf(0.0, 1.0); if( rval < 0.5 ){ x->channel[ i * 2 ] = 1; } else { x->channel[ i * 2 ] = 2; } ++(x->set_count); } else { x->channel[ i * 2 ] = 0; } x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc27_randf(.9,1.1); } } t_int *cavoc27_perform(t_int *w) { int i,j; float m1,m2; //////////// t_cavoc27 *x = (t_cavoc27 *) (w[1]); float *in = (t_float *)(w[2]); float *out = (t_float *)(w[3]); t_int n = w[4]; int frames_left = x->frames_left; float *input = x->input; float *buffer = x->buffer; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *output = x->output; float *channel = x->channel; float *tmpchannel = x->tmpchannel; float *ichannel = x->ichannel; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; int hold_frames = x->hold_frames; short *rule = x->rule; short left = x->left; short right = x->right; short center = x->center; float *last_frame = x->last_frame; float *c_lastphase_out = x->c_lastphase_out; float *c_lastphase_in = x->c_lastphase_in; float c_fundamental = x->c_fundamental; float c_factor_out = x->c_factor_out; float c_factor_in = x->c_factor_in; short interpolate_flag = x->interpolate_flag; if( x->mute ){ while( n-- ){ *out++ = 0.0; } return (w+5); } x->inCount += D; if( x->capture_flag || x->capture_lock ) { for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, x->inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, tmpchannel, N2, c_lastphase_in, c_fundamental, c_factor_in ); // ONLY COPY PHASES for( i = 1; i < N+2; i += 2 ){ channel[i] = tmpchannel[i]; // last_frame[i] = channel[i] = tmpchannel[i]; } if( x->capture_flag ){ --(x->capture_flag); } // on final frame - swap in channel (just phases though ) } if( --frames_left <= 0){ /* save composite frame for next time (only amps) */ /* for( i = 0; i < N+1; i++ ){ last_frame[i] = channel[i]; }*/ for( i = 0; i < N+1; i += 2 ){ last_frame[i] = channel[i]; } frames_left = hold_frames; for( i = 2; i < N; i+=2 ){ left = last_frame[ i - 2 ]; center = last_frame[i] ; right = last_frame[i+2]; channel[i] = cavoc27_apply_rule(left, right, center, rule ); } /* boundary cases */ center = last_frame[0]; right = last_frame[2]; left = last_frame[N]; channel[0] = cavoc27_apply_rule(left, right, center, rule ); center = last_frame[N]; right = last_frame[0]; left = last_frame[N - 2]; channel[N] = cavoc27_apply_rule(left, right, center, rule ); } if( interpolate_flag ){ m1 = (float) frames_left / (float) hold_frames ; m2 = 1.0 - m1; for( i = 0; i inCount = inCount; x->frames_left = frames_left; return (w+5); } int cavoc27_apply_rule( short left, short right, short center, short *rule){ if( left == 0 && center == 0 && right == 0 ) return rule[0]; if( left == 1 && center == 0 && right == 1 ) return rule[1]; if( left == 1 && center == 0 && right == 0 ) return rule[2]; if( left == 0 && center == 0 && right == 1 ) return rule[3]; if( left == 2 && center == 0 && right == 2 ) return rule[4]; if( left == 2 && center == 0 && right == 0 ) return rule[5]; if( left == 0 && center == 0 && right == 2 ) return rule[6]; if( left == 2 && center == 0 && right == 1 ) return rule[7]; if( left == 1 && center == 0 && right == 2 ) return rule[8]; if( left == 0 && center == 1 && right == 0 ) return rule[9]; if( left == 1 && center == 1 && right == 1 ) return rule[10]; if( left == 1 && center == 1 && right == 0 ) return rule[11]; if( left == 0 && center == 1 && right == 1 ) return rule[12]; if( left == 2 && center == 1 && right == 2 ) return rule[13]; if( left == 2 && center == 1 && right == 0 ) return rule[14]; if( left == 0 && center == 1 && right == 2 ) return rule[15]; if( left == 2 && center == 1 && right == 1 ) return rule[16]; if( left == 1 && center == 1 && right == 2 ) return rule[17]; if( left == 0 && center == 2 && right == 0 ) return rule[18]; if( left == 1 && center == 2 && right == 1 ) return rule[19]; if( left == 1 && center == 2 && right == 0 ) return rule[20]; if( left == 0 && center == 2 && right == 1 ) return rule[21]; if( left == 2 && center == 2 && right == 2 ) return rule[22]; if( left == 2 && center == 2 && right == 0 ) return rule[23]; if( left == 0 && center == 2 && right == 2 ) return rule[24]; if( left == 2 && center == 2 && right == 1 ) return rule[25]; if( left == 1 && center == 2 && right == 2 ) return rule[26]; return 0; //should never happen } float cavoc27_randf(float min, float max) { float randv, retval; randv = (float) (rand() % 32768) / 32768.0 ; return (retval = min + (max-min) * randv) ; } void cavoc27_dsp(t_cavoc27 *x, t_signal **sp, short *count) { if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr) { x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; cavoc27_init(x,1); } dsp_add(cavoc27_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/cavoc~-help.pd0000644000076500007650000000527312067450034015764 0ustar hanshans#N canvas 674 329 486 336 10; #N canvas 172 264 478 328 cavoc-block 0; #X obj 161 176 block~ 256; #X obj 167 155 outlet~; #X obj 292 69 inlet; #X obj 167 111 cavoc~ 0.05 150 4 1; #X text 133 127 args: density holdtime \, overlap \, window factor ; #X connect 2 0 3 0; #X connect 3 0 1 0; #X restore 29 72 pd cavoc-block; #X obj 29 143 dac~; #X msg 29 208 \; pd dsp \$1; #X obj 29 186 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X floatatom 80 96 5 0 0 0 - gain -; #X obj 32 261 hsl 128 15 0 1 0 0 gain gain-init gain -2 -6 0 8 -261127 -1 -1 0 1; #N canvas 773 396 486 336 messages 0; #X obj 120 243 outlet; #N canvas 321 426 474 324 rules 0; #X obj 55 273 outlet; #X msg 59 71 rule 1 1 1 1 0 0 0 0; #X msg 213 72 rule 1 0 1 0 1 0 1 0; #X msg 203 122 rule 0 0 0 0 0 1 0 1; #X msg 203 149 rule 0 1 1 0 1 0 0 1; #X msg 203 194 rule 0 0 0 0 1 1 1 1; #X msg 90 34 rule 1 1 0 1 0 1 0 0; #X msg 265 23 rule 1 1 0 1 0 1 1 0; #X msg 300 51 rule 1 1 0 0 1 1 0 0; #X msg 294 94 rule 0 0 1 0 1 0 1 1; #X msg 204 234 rule 0 0 0 1 1 0 0 0; #X msg 244 265 rule 1 0 0 1 1 0 0 1; #X text 38 301 rules define CA evolution of spectrum; #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 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 restore 250 227 pd rules; #N canvas 687 59 486 336 system 0; #X obj 209 277 outlet; #X msg 132 162 fftinfo; #X msg 64 181 mute \$1; #X obj 64 154 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 215 121 overlap \$1; #X msg 249 161 winfac \$1; #X floatatom 215 91 5 0 0 0 - - -; #X floatatom 249 142 5 0 0 0 - - -; #X text 243 240 default: overlap=4 \, winfac=1; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 4 0; #X connect 7 0 5 0; #X restore 41 177 pd system; #X floatatom 292 77 5 0 0 0 - - -; #X msg 291 101 density \$1; #X msg 251 44 0.05; #X msg 105 126 retune 0.5 2; #X msg 303 42 0.2; #X floatatom 316 163 5 0 0 0 - - -; #X msg 316 181 hold_time \$1; #X text 311 228 <- CA rules; #X text 220 149 hold time (in ms) for each step of CA; #X text 109 21 density is percent of bins turned on at start of CA ; #X text 96 102 reset phase "tunings"; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 4 0; #X connect 6 0 0 0; #X connect 7 0 3 0; #X connect 8 0 9 0; #X connect 9 0 0 0; #X restore 29 38 pd messages; #X obj 29 115 *~ 0.025; #X text 27 290 cavoc~ is an 8 rule cellular automaton that generates spectra. Start with very low gain.; #X connect 0 0 7 0; #X connect 3 0 2 0; #X connect 4 0 7 1; #X connect 6 0 0 0; #X connect 7 0 1 0; #X connect 7 0 1 1; fftease-2.5.2.git20121005/cavoc~.c0000644000076500007650000003332112067450034014650 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *cavoc_class; #endif #if PD static t_class *cavoc_class; #endif #define OBJECT_NAME "cavoc~" typedef struct _cavoc { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int in_count; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float frame_duration; int max_bin; float fundamental; float *last_frame; short left; short right; short center; short *rule; float density; float start_breakpoint; int hold_frames; int frames_left; int set_count; // FFT float *c_lastphase_out; float c_fundamental; float c_factor_out; float mult; float *trigland; int *bitshuffle; // void *list_outlet; t_atom *list_data; short mute; int overlap; int winfac; short external_trigger; float hold_time; } t_cavoc; void *cavoc_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *cavoc_perform(t_int *w); void cavoc_dsp(t_cavoc *x, t_signal **sp, short *count); void cavoc_assist(t_cavoc *x, void *b, long m, long a, char *s); void cavoc_free( t_cavoc *x ); int cavoc_apply_rule( short left, short right, short center, short *rule); float cavoc_randf(float min, float max); void cavoc_rule (t_cavoc *x, t_symbol *msg, short argc, t_atom *argv); void cavoc_density (t_cavoc *x, t_floatarg density); void cavoc_hold_time (t_cavoc *x, t_floatarg hold_time); void cavoc_retune (t_cavoc *x, t_floatarg min, t_floatarg max); void cavoc_mute (t_cavoc *x, t_floatarg toggle); void cavoc_external_trigger(t_cavoc *x, t_floatarg toggle); void cavoc_init(t_cavoc *x,short initialized); void cavoc_overlap(t_cavoc *x, t_floatarg f); void cavoc_winfac(t_cavoc *x, t_floatarg f); void cavoc_fftinfo(t_cavoc *x); #if MSP void main(void) { setup((t_messlist **)&cavoc_class, (method)cavoc_new, (method)cavoc_free, (short)sizeof(t_cavoc), 0, A_GIMME, 0); addmess((method)cavoc_dsp, "dsp", A_CANT, 0); addmess((method)cavoc_assist,"assist",A_CANT,0); addmess((method)cavoc_rule,"rule",A_GIMME,0); addmess((method)cavoc_density,"density",A_FLOAT,0); addmess((method)cavoc_hold_time,"hold_time",A_FLOAT,0); addmess((method)cavoc_mute,"mute",A_FLOAT,0); addmess((method)cavoc_external_trigger,"external_trigger",A_FLOAT,0); addmess((method)cavoc_retune,"retune",A_FLOAT,A_FLOAT,0); addmess((method)cavoc_overlap,"overlap",A_FLOAT,0); addmess((method)cavoc_winfac,"winfac",A_FLOAT,0); addmess((method)cavoc_fftinfo,"fftinfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void cavoc_tilde_setup(void){ cavoc_class = class_new(gensym("cavoc~"), (t_newmethod)cavoc_new, (t_method)cavoc_free ,sizeof(t_cavoc), 0,A_GIMME,0); CLASS_MAINSIGNALIN(cavoc_class, t_cavoc, x_f); class_addmethod(cavoc_class,(t_method)cavoc_dsp,gensym("dsp"),0); class_addmethod(cavoc_class,(t_method)cavoc_mute,gensym("mute"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_rule,gensym("rule"),A_GIMME,0); class_addmethod(cavoc_class,(t_method)cavoc_density,gensym("density"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_hold_time,gensym("hold_time"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_external_trigger,gensym("external_trigger"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_retune,gensym("retune"),A_FLOAT,A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(cavoc_class,(t_method)cavoc_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void cavoc_fftinfo( t_cavoc *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void cavoc_overlap(t_cavoc *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->overlap = (int)f; cavoc_init(x,1); } void cavoc_winfac(t_cavoc *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; cavoc_init(x,1); } void cavoc_external_trigger(t_cavoc *x, t_floatarg toggle) { x->external_trigger = toggle; } void cavoc_mute (t_cavoc *x, t_floatarg toggle) { x->mute = toggle; } void cavoc_retune(t_cavoc *x, t_floatarg min, t_floatarg max) { int i; if( max <= 0 || min <= 0 || min > max ){ error("bad values for min and max multipliers"); return; } if( min < .1 ) min = 0.1; if( max > 2.0 ) max = 2.0; for( i = 0; i < x->N2 + 1; i++ ){ x->channel[ i * 2 + 1 ] = x->c_fundamental * (float) (i / 2) * cavoc_randf(min, max); } } void cavoc_density(t_cavoc *x, t_floatarg density) { int i; if( density < 0.0001 ){ density = .0001; } else if( density > .9999 ){ density = 1.0; } x->density = density; x->start_breakpoint = 1.0 - x->density; for( i = 0; i < x->N2 + 1; i++ ){ if( cavoc_randf(0.0, 1.0) > x->start_breakpoint ){ x->channel[ i * 2 ] = 1; ++(x->set_count); } else { x->channel[ i * 2 ] = 0; } } for( i = 0; i < x->N+2; i++ ){ x->last_frame[i] = x->channel[i]; } } void cavoc_hold_time(t_cavoc *x, t_floatarg f) { if(f <= 0){ error("negative or zero hold time."); return; } x->hold_time = f; x->hold_frames = (int) ((x->hold_time/1000.0) / x->frame_duration); if( x->hold_frames < 1 ) x->hold_frames = 1; x->frames_left = x->hold_frames; } void cavoc_rule (t_cavoc *x, t_symbol *msg, short argc, t_atom *argv) { int i; short *rule = x->rule; if( argc != 8 ){ error("the rule must be size 8"); return; } for( i = 0; i < 8; i++ ){ rule[i] = (short) atom_getfloatarg(i, argc, argv); // post("%d",rule[i]); } } void cavoc_free( t_cavoc *x ){ #if MSP dsp_free((t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->input); free(x->Hwin); free(x->buffer); free(x->channel); free(x->last_frame); free(x->output); free(x->c_lastphase_out); free(x->rule); } void cavoc_assist (t_cavoc *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Trigger");break; } } else if (msg==2) { switch (arg) { case 0:sprintf(dst,"(signal) Output"); break; } } } void *cavoc_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_cavoc *x = (t_cavoc *)newobject(cavoc_class); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_cavoc *x = (t_cavoc *)pd_new(cavoc_class); outlet_new(&x->x_obj, gensym("signal")); #endif x->D = sys_getblksize(); x->R = sys_getsr(); x->density = atom_getfloatarg(0,argc,argv); x->hold_time = atom_getintarg(1,argc,argv); x->overlap = atom_getintarg(2,argc,argv); x->winfac = atom_getintarg(3,argc,argv); cavoc_init(x,0); return (x); } void cavoc_init(t_cavoc *x,short initialized) { int i; if(!x->D) x->D = 256; if(!x->R) x->R = 44100; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->mult = 1. / (float) x->N; x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->in_count = -(x->Nw); x->c_fundamental = (float) x->R/(float)((x->N2)<<1); x->frame_duration = (float)x->D/(float) x->R; if(x->hold_time <= 100) /* in milliseconds */ x->hold_time = 100; cavoc_hold_time(x, x->hold_time); if(!initialized){ srand(time(0)); x->mute = 0; x->set_count = 0; x->external_trigger = 0; if( x->density < 0.0 ){ x->density = 0; } else if( x->density > 1.0 ){ x->density = 1.0; } x->start_breakpoint = 1.0 - x->density; x->Wanal = (float *) calloc( MAX_Nw, sizeof(float) ); x->Wsyn = (float *) calloc( MAX_Nw, sizeof(float) ); x->input = (float *) calloc( MAX_Nw, sizeof(float) ); x->Hwin = (float *) calloc( MAX_Nw, sizeof(float) ); x->buffer = (float *) calloc( MAX_N, sizeof(float) ); x->channel = (float *) calloc( MAX_N+2, sizeof(float) ); x->last_frame = (float *) calloc(MAX_N+2, sizeof(float)); x->output = (float *) calloc( MAX_Nw, sizeof(float) ); x->bitshuffle = (int *) calloc( MAX_N * 2, sizeof( int ) ); x->trigland = (float *) calloc( MAX_N * 2, sizeof( float ) ); x->c_lastphase_out = (float *) calloc( MAX_N2+1, sizeof(float) ); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->rule = (short *) calloc(8, sizeof(short)); x->rule[2] = x->rule[3] = x->rule[5] = x->rule[6] = 1; x->rule[0] = x->rule[1] = x->rule[4] = x->rule[7] = 0; } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); memset((char *)x->last_frame,0,(x->N+2) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); for(i = 0; i < x->N2 + 1; i++){ if(cavoc_randf(0.0, 1.0) > x->start_breakpoint){ x->channel[ i * 2 ] = 1; ++(x->set_count); } else { x->channel[i * 2] = 0; } x->channel[i * 2 + 1] = x->c_fundamental * (float) (i / 2) * cavoc_randf(.9,1.1); } // post("turned on %d of a possible %d bins", x->set_count, x->N2+1 ); for( i = 0; i < x->N+2; i++ ){ x->last_frame[i] = x->channel[i]; } // post("cavoc~ FFT size: %d",x->N); } t_int *cavoc_perform(t_int *w) { int i,j; float oldfrac,newfrac; t_cavoc *x = (t_cavoc *)(w[1]); float *trigger_vec = (t_float *)(w[2]); float *out = (t_float *)(w[3]); t_int n = w[4]; int frames_left = x->frames_left; float *input = x->input; float *buffer = x->buffer; int in_count = x->in_count; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *output = x->output; float *channel = x->channel; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; int hold_frames = x->hold_frames; short *rule = x->rule; short left = x->left; short right = x->right; short center = x->center; float *last_frame = x->last_frame; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_out = x->c_factor_out; short external_trigger = x->external_trigger; short new_event = 0; in_count += D; if( x->mute ){ while( n-- ){ *out++ = 0.0; } return (w+5); } if(external_trigger){// only accurate to within a vector because of FFT for(i=0;iin_count = in_count % Nw; x->frames_left = frames_left; return (w+5); } int cavoc_apply_rule(short left, short right, short center, short *rule){ if( ! center ){ if( ! left && ! right){ return rule[0]; } else if ( ! left && right ){ return rule[1]; } else if ( left && ! right ) { return rule[2]; } else if (left && right) { return rule[3]; } } else { if( ! left && ! right){ return rule[4]; } else if ( ! left && right ){ return rule[5]; } else if ( left && ! right ) { return rule[6]; } else if (left && right) { return rule[7]; } } return 0;// never happens } float cavoc_randf(float min, float max) { float randv; randv = (float) (rand() % 32768) / 32768.0 ; return (min + ((max-min) * randv)) ; } void cavoc_dsp(t_cavoc *x, t_signal **sp, short *count) { if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; cavoc_init(x,1); } dsp_add(cavoc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/centerring~-help.pd0000644000076500007650000000460012067450034017022 0ustar hanshans#N canvas 281 24 648 434 10; #N canvas 376 316 462 312 centerring-block 0; #X obj 163 128 centerring~; #X obj 233 219 block~ 256; #X obj 152 180 outlet~; #X obj 141 63 inlet~; #X obj 337 89 inlet; #X obj 195 67 inlet; #X obj 242 66 inlet; #X obj 290 71 inlet; #X connect 0 0 2 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 3; #X restore 167 141 pd centerring-block; #X obj 167 195 *~ 1; #X obj 167 230 dac~; #X floatatom 190 176 5 0 0 0 - centerring-gain -; #X msg 333 242 \; pd dsp \$1; #X obj 333 225 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 18 207 hsl 128 15 0 0.1 0 0 centerring-gain empty output_gain -2 -6 0 8 -79789 -1 -1 800 1; #X obj 81 51 phasor~ 150; #N canvas 0 22 474 324 messages 0; #X obj 159 192 outlet; #X msg 154 138 zerophases; #X msg 263 138 randphases; #X msg 71 101 seed \$1; #X floatatom 70 71 5 0 0 0 - - -; #X msg 117 65 1974; #X obj 320 168 fftease-system; #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 5 0 3 0; #X connect 6 0 0 0; #X restore 319 108 pd messages; #X floatatom 193 54 5 0 0 0 - cr-base-frequency -; #X obj 18 240 hsl 128 15 0.1 20 0 0 cr-base-frequency empty base_frequency -2 -6 0 8 -79789 -1 -1 900 1; #X floatatom 251 59 5 0 0 0 - cr-bandwidth -; #X obj 16 271 hsl 128 15 0.1 20 0 0 cr-bandwidth empty bandwidth -2 -6 0 8 -79789 -1 -1 7700 1; #X floatatom 329 42 5 0 0 0 - cr-freq-constant -; #X obj 15 305 hsl 128 15 0.1 20 0 0 cr-freq-constant empty frequency_constant -2 -6 0 8 -79789 -1 -1 6300 1; #X obj 9 99 loadbang; #X msg 9 125 0.1 1 0.15 1; #X obj 9 157 unpack f f f f; #X text 171 294 centerring~ performs frequency independent amplitude modulation upon the spectral magnitudes of input signals. The effect is somewhat akin to flanging. The base frequency is used to derive the frequency of an oscillator associated with each frequency band. The frequency bandwidth and constant control the deviation of a particular frequency band's modulation oscillator frequency.; #X floatatom 81 30 5 0 0 0 - - -; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 1 0 2 1; #X connect 3 0 1 1; #X connect 5 0 4 0; #X connect 7 0 0 0; #X connect 8 0 0 4; #X connect 9 0 0 1; #X connect 11 0 0 2; #X connect 13 0 0 3; #X connect 15 0 16 0; #X connect 16 0 17 0; #X connect 17 0 6 0; #X connect 17 1 10 0; #X connect 17 2 12 0; #X connect 17 3 14 0; #X connect 19 0 7 0; fftease-2.5.2.git20121005/centerring~.c0000644000076500007650000003506012067450034015717 0ustar hanshans#include "MSPd.h" #include "fftease.h" #include "PenroseOscil.h" #include "PenroseRand.h" #define OBJECT_NAME "centerring~" #define MAX_WARP 16.0 #if MSP void *centerring_class; #endif #if PD static t_class *centerring_class; #endif #define OBJECT_NAME "centerring~" typedef struct _centerring { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int bufferLength; int recalc; int seed; int *bitshuffle; float baseFreq; float constFreq; float bandFreq; float frameR; float *ringPhases; float *ringIncrements; float *sineBuffer; float *Wanal; float *Wsyn; float *inputOne; float *Hwin; float *bufferOne; float *channelOne; float *newChannel; float *newAmplitudes; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_centerring; /* msp function prototypes */ void *centerring_new(t_symbol *s, int argc, t_atom *argv); t_int *centerring_perform(t_int *w); void centerring_dsp(t_centerring *x, t_signal **sp, short *count); void centerring_float(t_centerring *x, double myFloat); void centerring_assist(t_centerring *x, void *b, long m, long a, char *s); void centerring_dest(t_centerring *x, double f); void centerring_messages(t_centerring *x, t_symbol *s, short argc, t_atom *argv); void centerring_adjust( t_centerring *x ); void centerring_zerophases( t_centerring *x ); void centerring_randphases( t_centerring *x ); void centerring_free(t_centerring *x); void centerring_init(t_centerring *x, short initialized); void centerring_mute(t_centerring *x, t_floatarg toggle); void centerring_overlap(t_centerring *x, t_floatarg o); void centerring_fftinfo( t_centerring *x ); void centerring_winfac(t_centerring *x, t_floatarg f); /* float input handling routine for shape width (MSP only) */ #if MSP void centerring_float( t_centerring *x, t_floatarg df ) { float myFloat = (float) df; int inlet = x->x_obj.z_in; if ( inlet == 1 ) { x->baseFreq = myFloat; x->recalc = 1; } if ( inlet == 2 ) { x->bandFreq = myFloat; x->recalc = 1; } if ( inlet == 3 ) { x->constFreq = myFloat; x->recalc = 1; } } void main(void) { setup( (struct messlist **) ¢erring_class, (method) centerring_new, (method) centerring_free, (short) sizeof(t_centerring), 0,A_GIMME, 0); addmess((method)centerring_dsp, "dsp", A_CANT, 0); addmess((method)centerring_assist,"assist",A_CANT,0); addmess((method)centerring_messages,"seed", A_GIMME, 0); addmess((method)centerring_messages,"zerophases", A_GIMME, 0); addmess((method)centerring_messages,"randphases", A_GIMME, 0); addmess((method)centerring_mute,"mute", A_FLOAT, 0); addmess((method)centerring_overlap,"overlap", A_FLOAT, 0); addmess((method)centerring_winfac,"winfac", A_FLOAT, 0); addmess((method)centerring_fftinfo,"fftinfo", 0); addfloat((method)centerring_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void centerring_tilde_setup(void) { centerring_class = class_new(gensym("centerring~"), (t_newmethod)centerring_new, (t_method)centerring_free ,sizeof(t_centerring), 0,A_GIMME,0); CLASS_MAINSIGNALIN(centerring_class, t_centerring, x_f); class_addmethod(centerring_class, (t_method)centerring_dsp, gensym("dsp"), 0); class_addmethod(centerring_class, (t_method)centerring_assist, gensym("assist"), 0); class_addmethod(centerring_class, (t_method)centerring_messages, gensym("seed"), A_GIMME,0); class_addmethod(centerring_class, (t_method)centerring_messages, gensym("zerophases"), A_GIMME,0); class_addmethod(centerring_class, (t_method)centerring_messages, gensym("randphases"), A_GIMME,0); class_addmethod(centerring_class, (t_method)centerring_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(centerring_class, (t_method)centerring_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(centerring_class, (t_method)centerring_mute, gensym("mute"), A_FLOAT,0); class_addmethod(centerring_class, (t_method)centerring_fftinfo, gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void centerring_messages(t_centerring *x, t_symbol *s, short argc, t_atom *argv) { if (s == gensym("seed")) x->seed = (int) atom_getfloatarg(0,argc,argv); if (s == gensym("zerophases")) centerring_zerophases( x ); if (s == gensym("randphases")) centerring_randphases( x ); } /* diagnostic messages for Max */ void centerring_assist (t_centerring *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Base Modulation Frequency"); break; case 2: sprintf(dst,"(signal/float) Frequency Deviation Bandwidth"); break; case 3: sprintf(dst,"(signal/float) Frequency Deviation Constant"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void *centerring_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_centerring *x = (t_centerring *) newobject(centerring_class); dsp_setup((t_pxobject *)x, 4); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_centerring *x = (t_centerring *)pd_new(centerring_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: baseFreq, bandFreq, constFreq, seed, overlap, winfac */ x->overlap = x->winfac = 0; x->baseFreq = atom_getfloatarg(0,argc,argv); x->bandFreq = atom_getfloatarg(1,argc,argv); x->constFreq = atom_getfloatarg(2,argc,argv); x->seed = atom_getfloatarg(3,argc,argv); x->overlap = atom_getfloatarg(4,argc,argv); x->winfac = atom_getfloatarg(5,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } if(x->baseFreq <= 0.0) x->baseFreq = 1.; if(x->bandFreq <= 0.0) x->bandFreq = .2; if(x->constFreq <= 0) x->constFreq = 1.; x->vs = sys_getblksize(); x->R = sys_getsr(); centerring_init(x,0); return(x); } void centerring_init(t_centerring *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->frameR = (float) x->R / (float) x->D; if(!initialized){ x->mute = 0; x->bufferLength = 131072; x->recalc = 0; x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->inputOne = (float *) calloc(MAX_Nw, sizeof(float)); x->bufferOne = (float *) calloc(MAX_N, sizeof(float)); x->channelOne = (float *) calloc((MAX_N+2), sizeof(float)); x->newChannel = (float *) calloc(MAX_N+2, sizeof(float)); x->newAmplitudes = (float *) calloc(((MAX_N2 + 1) * 16), sizeof(float) ); x->ringPhases = (float *) calloc((MAX_N2 + 1), sizeof(float)); x->ringIncrements = (float *) calloc((MAX_N2 + 1), sizeof(float)); x->sineBuffer = (float *) calloc((x->bufferLength + 1), sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); } memset((char *)x->inputOne,0,x->Nw); memset((char *)x->output,0,x->Nw); memset((char *)x->bufferOne,0,x->N); memset((char *)x->channelOne,0,x->N+2); memset((char *)x->newChannel,0,x->N+2); memset((char *)x->ringPhases,0,(x->N2+1)); memset((char *)x->ringIncrements,0,(x->N2+1)); memset((char *)x->newAmplitudes,0,(x->N2+1)); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); makeSineBuffer(x->sineBuffer, x->bufferLength); centerring_adjust(x); centerring_zerophases(x); } void centerring_free(t_centerring *x) { #if MSP dsp_free((t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->Hwin); free(x->inputOne); free(x->bufferOne); free(x->channelOne); free(x->output); free(x->newChannel); free(x->newAmplitudes); free(x->ringPhases); free(x->ringIncrements); free(x->sineBuffer); } void centerring_adjust( t_centerring *x ) { int i; float *ringIncrements = x->ringIncrements, *ringPhases = x->ringPhases; /* initialize oscillator increments and phases */ for (i=0; i < x->N2; i++) { *(ringIncrements+i) = frequencyToIncrement( x->frameR, x->baseFreq * ( (rrand(&(x->seed)) * x->bandFreq) + x->constFreq ), x->bufferLength ); } } void centerring_zerophases( t_centerring *x ) { int i; for (i=0; i < x->N2; i++) *((x->ringPhases)+i) = 0.; } void centerring_randphases( t_centerring *x ) { int i; for (i=0; i < x->N2; i++) *((x->ringPhases)+i) = prand(&(x->seed)) * (float) (x->bufferLength); } t_int *centerring_perform(t_int *w) { int i,j, bindex, inCount, R, N, N2, D, Nw, newLength, bufferLength, even, odd, *bitshuffle; float mult, bandFreq, constFreq, baseFreq, a1, b1, interpIncr, interpPhase, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *ringPhases, *ringIncrements, *sineBuffer, *channelOne, *newChannel, *newAmplitudes, *trigland; t_centerring *x = (t_centerring *) (w[1]); t_float *inOne = (t_float *) (w[2]); t_float *vec_baseFreq = (t_float *) (w[3]); t_float *vec_bandFreq = (t_float *) (w[4]); t_float *vec_constFreq = (t_float *) (w[5]); t_float *out = (t_float *)(w[6]); t_int n = (int) (w[7]); short *connected = x->connected; if(connected[1]){ x->recalc = 1; x->baseFreq = *vec_baseFreq; } if(connected[2]){ x->recalc = 1; x->bandFreq = *vec_bandFreq; } if(connected[3]){ x->recalc = 1; x->constFreq = *vec_constFreq; } if(x->mute){ while(n--) *out++ = 0.0; return (w+8); } /* dereference structure */ inputOne = x->inputOne; bufferOne = x->bufferOne; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; newChannel = x->newChannel; newAmplitudes = x->newAmplitudes; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; bufferLength = x->bufferLength; ringPhases = x->ringPhases; ringIncrements = x->ringIncrements; sineBuffer = x->sineBuffer; /* recalculate our oscillator values if object inputs have been updated */ if (x->recalc) centerring_adjust( x ); x->recalc = 0; /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) inputOne[j] = inputOne[j+D]; for ( j = Nw - D; j < Nw; j++ ) inputOne[j] = *inOne++; /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); /* replace signal one's phases with those of signal two */ *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); } /* perform ring modulation on successive fft frames */ for (i=0; i < N2; i++) { even = i<<1; *(channelOne+even) *= bufferOscil( ringPhases+i, *(ringIncrements+i), sineBuffer, bufferLength ); } /* convert from polar to cartesian */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+8); } void centerring_mute(t_centerring *x, t_floatarg toggle) { x->mute = (short)toggle; } void centerring_overlap(t_centerring *x, t_floatarg o) { if(!fftease_power_of_two((int)o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; centerring_init(x,1); } void centerring_winfac(t_centerring *x, t_floatarg f) { if(!fftease_power_of_two((int)f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; centerring_init(x,1); } void centerring_fftinfo( t_centerring *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void centerring_dsp(t_centerring *x, t_signal **sp, short *count) { int i; #if MSP for( i = 0; i < 4; i++ ){ x->connected[i] = count[i]; } #endif #if PD for( i = 0; i < 4; i++ ){ x->connected[i] = 1; } #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; centerring_init(x,1); } dsp_add(centerring_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/codepend~-help.pd0000644000076500007650000001041412067450034016443 0ustar hanshans#N canvas 281 24 668 454 10; #X obj 167 237 *~ 1; #X obj 167 289 dac~; #X floatatom 190 218 5 0 0 0 - centerring-gain -; #X msg 333 284 \; pd dsp \$1; #X obj 333 267 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 17 207 hsl 128 15 0 4 0 0 centerring-gain empty output_gain -2 -6 0 8 -79789 -1 -1 317 1; #N canvas 0 22 519 354 messages 0; #X obj 132 268 outlet; #X text 30 194 turn on invert; #X msg 132 175 pad \$1; #X obj 132 146 ampdb; #X floatatom 132 116 5 -200 -12 0 - - -; #X text 221 177 is turned on; #X obj 9 195 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 9 217 invert \$1; #X text 221 163 pad affects the gain only when "invert"; #X obj 184 233 fftease-system; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 6 0 7 0; #X connect 7 0 0 0; #X connect 9 0 0 0; #X restore 448 167 pd messages; #X obj 18 240 hsl 128 15 0.15 1 0 0 cod-scaling-exponent empty scaling_exponent -2 -6 0 8 -88868 -1 -1 2241 1; #N canvas 376 316 470 320 codepend-block 0; #X obj 233 219 block~ 256; #X obj 163 185 outlet~; #X obj 163 38 inlet~; #X obj 269 107 inlet; #X obj 201 81 inlet; #X obj 221 98 inlet; #X obj 163 128 codepend~; #X obj 182 65 inlet~; #X connect 2 0 6 0; #X connect 3 0 6 0; #X connect 4 0 6 2; #X connect 5 0 6 3; #X connect 6 0 1 0; #X connect 7 0 6 1; #X restore 167 183 pd codepend-block; #X obj 252 142 ampdb; #X floatatom 252 122 5 0 0 0 - cod-inverse-threshold -; #X floatatom 252 164 5 0 0 0 - - -; #N canvas 990 218 504 393 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 177 read -resize \$1 codepend-sound1; #N canvas 0 22 450 300 graph1 0; #X array codepend-sound1 501762 float 2; #X coords 0 1 501761 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X obj 227 268 tabplay~ codepend-sound1; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 4 0 1 0; #X connect 6 0 5 0; #X connect 6 1 8 0; #X connect 7 0 6 0; #X connect 8 0 7 0; #X connect 9 0 8 1; #X restore 167 22 pd playsound1; #N canvas 990 218 508 397 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #X msg 31 177 read -resize \$1 codepend-sound2; #N canvas 0 22 450 300 graph2 0; #X array codepend-sound2 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 216 15 graph; #X obj 227 268 tabplay~ codepend-sound2; #X connect 1 0 11 0; #X connect 2 0 1 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 11 0 0 0; #X connect 13 0 3 0; #X connect 13 1 5 0; #X restore 195 40 pd playsound2; #X floatatom 224 90 5 0 0 0 - cod-scaling-exponent -; #X obj 19 278 hsl 128 15 -90 0 0 0 cod-inverse-threshold empty inverse_threshold -2 -6 0 8 -88868 -1 -1 7620 1; #X text 296 137 but only when "invert" is turned on); #X text 224 72 scaling exponent (lower values increase distortion) ; #X text 294 31 <- load and loop two soundfiles to hear effect; #X msg 14 123 0.1 0.3 -36; #X obj 14 139 unpack f f f; #X obj 14 107 loadbang; #X text 293 121 inverse threshold (lower values intensify effect; #X text 31 316 codepend~ is a classic "block convolution" processor. It performs a complex multiply upon the spectra of two input signals. Multiplication of spectra can cause significant drops in the amplitude of the output signal. The invert message causes codepend~ to perform complex division of the input spectra rather than multiplication. This can cause huge amplitude gains. A "pad" message is provided to allow for empirical amplitude balancing between the normal and "invert" states. ; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 2 0 0 1; #X connect 4 0 3 0; #X connect 6 0 8 4; #X connect 8 0 0 0; #X connect 9 0 11 0; #X connect 10 0 9 0; #X connect 11 0 8 3; #X connect 12 0 8 0; #X connect 13 0 8 1; #X connect 14 0 8 2; #X connect 19 0 20 0; #X connect 20 0 5 0; #X connect 20 1 7 0; #X connect 20 2 15 0; #X connect 21 0 19 0; fftease-2.5.2.git20121005/codepend~.c0000644000076500007650000003536612067450034015351 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *codepend_class; #endif #if PD static t_class *codepend_class; #endif #define OBJECT_NAME "codepend~" /* Adding -32dB pad for invert option. Also added latency mechanism in switching from normal to "invert" to avoid glitches from extreme amplitude disparities. Made all inlets of type signal (with float options). Threshold input is now linear, not dB (with Max doing the conversion if desired). -EL 10/1/2005 */ typedef struct _codepend { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int invert; int *bitshuffle; float threshold; float exponent; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size int invert_countdown; // delay onset of invert effect to avoid loud glitches int invert_nextstate;// next state for invert float invert_pad; } t_codepend; /* msp function prototypes */ void *codepend_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *codepend_perform(t_int *w); void codepend_dsp(t_codepend *x, t_signal **sp, short *count); void codepend_assist(t_codepend *x, void *b, long m, long a, char *s); void codepend_dest(t_codepend *x, double f); void codepend_invert(t_codepend *x, t_floatarg toggle); void codepend_free(t_codepend *x); void codepend_mute(t_codepend *x, t_floatarg toggle); void codepend_fftinfo(t_codepend *x); void codepend_tilde_setup(void); void codepend_winfac(t_codepend *x, t_floatarg o); void codepend_overlap(t_codepend *x, t_floatarg o); void codepend_init(t_codepend *x, short initialized); void codepend_pad(t_codepend *x, t_floatarg pad); #if MSP void main(void) { setup( (struct messlist **) &codepend_class, (void *) codepend_new, (method)dsp_free, (short) sizeof(t_codepend), 0, A_GIMME, 0); addmess((method)codepend_dsp, "dsp", A_CANT, 0); addmess((method)codepend_assist,"assist",A_CANT,0); addmess((method)codepend_invert,"invert", A_FLOAT, 0); addmess((method)codepend_mute,"mute", A_FLOAT, 0); addmess((method)codepend_pad,"pad", A_FLOAT, 0); addmess((method)codepend_overlap,"overlap", A_FLOAT, 0); addmess((method)codepend_winfac,"winfac", A_FLOAT, 0); addmess((method)codepend_fftinfo,"fftinfo", 0); addfloat((method) codepend_dest); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } /* float input handling routine (MSP only)*/ void codepend_dest(t_codepend *x, double df) { float f = (float) df; int inlet = x->x_obj.z_in; if ( inlet == 2 ) { x->exponent = f; } if ( inlet == 3 ){ /* x->threshold = (float) (pow( 10., (f * .05))); */ x->threshold = f; } } #endif #if PD void codepend_tilde_setup(void) { codepend_class = class_new(gensym("codepend~"), (t_newmethod)codepend_new, (t_method)codepend_free ,sizeof(t_codepend), 0,A_GIMME,0); CLASS_MAINSIGNALIN(codepend_class, t_codepend, x_f); class_addmethod(codepend_class, (t_method)codepend_dsp, gensym("dsp"), 0); class_addmethod(codepend_class, (t_method)codepend_assist, gensym("assist"), 0); class_addmethod(codepend_class, (t_method)codepend_invert, gensym("invert"), A_FLOAT,0); class_addmethod(codepend_class, (t_method)codepend_mute, gensym("mute"), A_FLOAT,0); class_addmethod(codepend_class, (t_method)codepend_pad, gensym("pad"), A_FLOAT,0); class_addmethod(codepend_class, (t_method)codepend_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(codepend_class, (t_method)codepend_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(codepend_class, (t_method)codepend_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void codepend_mute(t_codepend *x, t_floatarg toggle) { x->mute = (short)toggle; // post("mute set to %f, %d",toggle,x->mute); } void codepend_overlap(t_codepend *x, t_floatarg o) { if(!fftease_power_of_two((int)o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; codepend_init(x,1); } void codepend_winfac(t_codepend *x, t_floatarg f) { if(!fftease_power_of_two((int)f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; codepend_init(x,1); } void codepend_fftinfo( t_codepend *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void codepend_free(t_codepend *x) { #if MSP dsp_free((t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->Hwin); free(x->inputOne); free(x->inputTwo); free(x->bufferOne); free(x->bufferTwo); free(x->channelOne); free(x->channelTwo); free(x->output); } void codepend_pad(t_codepend *x, t_floatarg pad) { x->invert_pad = pad; codepend_invert(x,x->invert);//resubmit to invert } void codepend_invert(t_codepend *x, t_floatarg toggle) { x->invert_nextstate = (short)toggle; x->invert_countdown = x->overlap; // delay effect for "overlap" vectors if(x->invert_nextstate){ // lower gain immediately; delay going to invert x->mult = (1. / (float) x->N) * x->invert_pad; } else { x->invert = 0; //immediately turn off invert; delay raising gain } } void codepend_assist (t_codepend *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input One");break; case 1: sprintf(dst,"(signal) Input Two"); break; case 2: sprintf(dst,"(signal/float) Scaling Exponent"); break; case 3: sprintf(dst,"(signal/float) Inverse Threshold"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void *codepend_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_codepend *x = (t_codepend *) newobject(codepend_class); dsp_setup((t_pxobject *)x,4); outlet_new((t_pxobject *)x, "signal"); // x->x_obj.z_misc |= Z_NO_INPLACE; // probably not needed #endif #if PD t_codepend *x = (t_codepend *)pd_new(codepend_class); /* add three additional signal inlets */ inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: scaling exponent, threshold (now linear), overlap, winfac */ x->exponent = atom_getfloatarg(0,argc,argv); x->threshold = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); /* x->threshold = (float) pow(10.0,(x->threshold * .05)); */ /* sanity check */ if(x->exponent < 0.25) x->exponent = 0.25; if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } x->vs = sys_getblksize(); x->R = sys_getsr(); codepend_init(x,0); return (x); } void codepend_init(t_codepend *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->invert_pad = 0.025; // -32 dB x->invert_countdown = 0; x->mute = 0; x->invert = 0; x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->inputOne = (float *) calloc(MAX_Nw, sizeof(float)); x->inputTwo = (float *) calloc(MAX_Nw, sizeof(float)); x->bufferOne = (float *) calloc(MAX_N, sizeof(float)); x->bufferTwo = (float *) calloc(MAX_N, sizeof(float)); x->channelOne = (float *) calloc(MAX_N+2, sizeof(float)); x->channelTwo = (float *) calloc(MAX_N+2, sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); } memset((char *)x->inputOne,0,x->Nw); memset((char *)x->inputTwo,0,x->Nw); memset((char *)x->output,0,x->Nw); memset((char *)x->bufferOne,0,x->N); memset((char *)x->bufferTwo,0,x->N); memset((char *)x->channelOne,0,(x->N+2)); memset((char *)x->channelTwo,0,(x->N+2)); if(x->invert){ x->mult *= x->invert_pad; } init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1); } t_int *codepend_perform(t_int *w) { int i,j, inCount, R, N, N2, D, Nw, invert = 0, even, odd, *bitshuffle; float maxamp, threshold = 1., mult, exponent, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; /* get our inlets and outlets */ t_codepend *x = (t_codepend *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *vec_exponent = (t_float *)(w[4]); t_float *vec_threshold = (t_float *)(w[5]); t_float *out = (t_float *)(w[6]); t_int n = w[7]; short *connected = x->connected; /* dereference structure */ if(connected[2]) x->exponent = *vec_exponent; if(connected[3]){ x->threshold = *vec_threshold; /* x->threshold = (float) (pow( 10., (x->threshold * .05))); */ } if(x->mute){ while(n--) *out++ = 0.0; return w+8; } // do countdown if(x->invert_countdown > 0){ if(x->invert) { // we } else { } --(x->invert_countdown); if(! x->invert_countdown){ // countdown just ended if(x->invert_nextstate){ // moving to invert (gain is already down) x->invert = x->invert_nextstate; } else { // invert is already off - now reset gain x->mult = 1. / (float) x->N; } } } inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; invert = x->invert; exponent = x->exponent; if ( x->threshold != 0. ) threshold = x->threshold; /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ if (invert) { for ( i = 0; i <= N2; i++ ) { float mag_1, mag_2; odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); /* complex division */ mag_1 = hypot( a1, b1 ); mag_2 = hypot( a2, b2 ); if ( mag_2 > threshold ) *(channelOne+even) = mag_1 / mag_2; else *(channelOne+even) = mag_1 / threshold; if ( mag_1 != 0. && mag_2 != 0. ) *(channelOne+odd) = atan2( b2, a2 ) - atan2( b1, a1 ); else *(channelOne+odd) = 0.; /* raise resulting magnitude to a desired power */ *(channelOne+even) = pow( *(channelOne+even), exponent ); } } else { for ( i = 0; i <= N2; i++ ) { float f_real, f_imag; odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); /* complex multiply */ f_real = (a1 * a2) - (b1 * b2); f_imag = (a1 * b2) + (b1 * a2); *(channelOne+even) = hypot( f_real, f_imag ); *(channelOne+odd) = -atan2( f_imag, f_real ); /* raise resulting magnitude to a desired power */ *(channelOne+even) = pow( *(channelOne+even), exponent ); } } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+8); } void codepend_dsp(t_codepend *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 4; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 4; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; codepend_init(x,1); } dsp_add(codepend_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/convert.c0000644000076500007650000000263412067450034015042 0ustar hanshans#include "fftease.h" /* S is a spectrum in rfft format, i.e., it contains N real values arranged as real followed by imaginary values, except for first two values, which are real parts of 0 and Nyquist frequencies; convert first changes these into N/2+1 PAIRS of magnitude and phase values to be stored in output array C; the phases are then unwrapped and successive phase differences are used to compute estimates of the instantaneous frequencies for each phase vocoder analysis channel; decimation rate D and sampling rate R are used to render these frequency values directly in Hz. */ void convert(float *S, float *C, int N2, float *lastphase, float fundamental, float factor ) { float phase, phasediff; int real, imag, amp, freq; float a, b; int i; /* float myTWOPI, myPI; */ /* double sin(), cos(), atan(), hypot();*/ /* myTWOPI = 8.*atan(1.); myPI = 4.*atan(1.); */ for ( i = 0; i <= N2; i++ ) { imag = freq = ( real = amp = i<<1 ) + 1; a = ( i == N2 ? S[1] : S[real] ); b = ( i == 0 || i == N2 ? 0. : S[imag] ); C[amp] = hypot( a, b ); if ( C[amp] == 0. ) phasediff = 0.; else { phasediff = ( phase = -atan2( b, a ) ) - lastphase[i]; lastphase[i] = phase; while ( phasediff > PI ) phasediff -= TWOPI; while ( phasediff < -PI ) phasediff += TWOPI; } C[freq] = phasediff*factor + i*fundamental; } } fftease-2.5.2.git20121005/crossx~-help.pd0000644000076500007650000000727712067450034016220 0ustar hanshans#N canvas 684 407 470 320 10; #X obj 25 189 dac~; #N canvas 0 22 470 320 rich-harmonic-source 0; #X obj 127 232 outlet~; #X obj 127 125 phasor~ 100; #X obj 212 126 phasor~ 125; #X obj 296 125 phasor~ 150; #X obj 127 183 *~ 0.3; #X floatatom 127 67 5 0 0 0 - - -; #X obj 212 99 * 1.25; #X obj 296 100 * 1.5; #X obj 130 34 hsl 128 15 60 600 0 0 empty empty empty -2 -6 0 8 -154413 -1 -1 8900 1; #X connect 1 0 4 0; #X connect 2 0 4 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 6 0; #X connect 5 0 1 0; #X connect 5 0 7 0; #X connect 6 0 2 0; #X connect 7 0 3 0; #X connect 8 0 5 0; #X restore 25 23 pd rich-harmonic-source; #X floatatom 91 66 5 0 0 0 - - -; #N canvas 179 221 657 470 vocal-source 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array crossx-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 crossx-sound1; #X obj 227 268 tabplay~ crossx-sound1; #X connect 2 0 12 0; #X connect 4 0 2 0; #X connect 6 0 13 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 1 0; #X connect 13 0 5 0; #X connect 13 1 7 0; #X restore 58 45 pd vocal-source; #X msg 186 229 \; pd dsp \$1; #X obj 186 208 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 25 160 *~ 1; #X floatatom 48 141 5 0 0 0 - - -; #X text 90 143 <- might need large amplitude; #X text 96 155 but watch for sudden spikes!; #X text 133 70 <- synthesis advancement threshold; #N canvas 172 351 466 316 crossx-block 0; #X obj 161 178 outlet~; #X obj 161 49 inlet~; #X obj 219 100 inlet; #X obj 283 102 inlet; #X obj 161 213 block~ 256; #X obj 190 80 inlet~; #X obj 161 132 crossx~ 4; #X connect 1 0 6 0; #X connect 2 0 6 2; #X connect 3 0 6 0; #X connect 5 0 6 1; #X connect 6 0 0 0; #X restore 25 88 pd crossx-block; #N canvas 0 22 458 308 messages 0; #X obj 56 233 outlet; #X msg 56 175 autonorm \$1; #X text 56 66 frame normalization to tame amplitude spikes; #X obj 209 217 fftease-system; #N canvas 0 22 458 308 rescale-autonorm 0; #X obj 93 30 inlet; #X obj 61 92 t b b; #X msg 61 115 1; #X msg 108 118 0.05; #X obj 108 144 s output-gain; #X obj 96 221 outlet; #X obj 197 49 inlet; #X obj 226 102 t b b; #X obj 243 237 s output-gain; #X msg 313 130 0; #X msg 243 211 5; #X obj 261 174 pipe 100; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 2 0 5 0; #X connect 3 0 4 0; #X connect 6 0 7 0; #X connect 7 0 11 0; #X connect 7 1 9 0; #X connect 9 0 5 0; #X connect 10 0 8 0; #X connect 11 0 10 0; #X restore 56 122 pd rescale-autonorm; #X obj 56 93 bng 15 250 50 0 empty empty on 0 -6 0 8 -262144 -1 -1 ; #X obj 184 94 bng 15 250 50 0 empty empty off 0 -6 0 8 -262144 -1 -1 ; #X connect 1 0 0 0; #X connect 3 0 0 0; #X connect 4 0 1 0; #X connect 5 0 4 0; #X connect 6 0 4 1; #X restore 143 88 pd messages; #X obj 48 118 r output-gain; #X text 96 170 a compressor could be useful here; #X obj 215 51 hsl 128 15 0 0.05 0 0 empty empty empty -2 -6 0 8 -191432 -1 -1 700 1; #X text 26 262 crossx~ is related to xsyn~ but uses a threshold to determine whether to perform spectral multiplication or maintain the last calculated amplitude/phase pair. crossx~ is also somewhat less CPU intensive.; #X connect 1 0 11 0; #X connect 2 0 11 2; #X connect 3 0 11 1; #X connect 5 0 4 0; #X connect 6 0 0 0; #X connect 6 0 0 1; #X connect 7 0 6 1; #X connect 11 0 6 0; #X connect 12 0 11 3; #X connect 13 0 7 0; #X connect 15 0 2 0; fftease-2.5.2.git20121005/crossx~.c0000644000076500007650000002760512067450034015106 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *crossx_class; #endif #if PD static t_class *crossx_class; #endif #define OBJECT_NAME "crossx~" typedef struct _crossx { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; float *input1; float *buffer1; float *channel1; float *input2; float *buffer2; float *channel2; float *last_channel; // int inCount; float *Hwin; float *Wanal; float *Wsyn; float *output; /* crossx vars */ float *c_lastphase_in1; float *c_lastphase_in2; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; float threshie; short thresh_connected; // for fast fft float mult; float *trigland; int *bitshuffle; int overlap;//overlap factor int winfac;//window factor int vs;//vector size short mute;//flag short autonorm;// for self gain regulation } t_crossx; void *crossx_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *crossx_perform(t_int *w); void crossx_dsp(t_crossx *x, t_signal **sp, short *count); void crossx_assist(t_crossx *x, void *b, long m, long a, char *s); void crossx_float(t_crossx *x, double f); void *crossx_new(t_symbol *s, int argc, t_atom *argv); void crossx_init(t_crossx *x, short initialized); void crossx_overlap(t_crossx *x, t_floatarg o); void crossx_winfac(t_crossx *x, t_floatarg o); void crossx_fftinfo(t_crossx *x); void crossx_mute(t_crossx *x, t_floatarg toggle); void crossx_autonorm(t_crossx *x, t_floatarg toggle); void crossx_free(t_crossx *x); #if MSP void main(void) { setup((t_messlist **)&crossx_class, (method)crossx_new, (method)dsp_free, (short)sizeof(t_crossx), 0L, A_GIMME, 0); addmess((method)crossx_dsp, "dsp", A_CANT, 0); addmess((method)crossx_assist,"assist",A_CANT,0); addmess((method)crossx_mute,"mute",A_DEFFLOAT,0); addmess((method)crossx_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)crossx_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)crossx_fftinfo, "fftinfo", 0); addmess((method)crossx_autonorm, "autonorm", A_DEFFLOAT, 0); addfloat((method)crossx_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void crossx_tilde_setup(void) { crossx_class = class_new(gensym("crossx~"), (t_newmethod)crossx_new, (t_method)crossx_free ,sizeof(t_crossx), 0,A_GIMME,0); CLASS_MAINSIGNALIN(crossx_class, t_crossx, x_f); class_addmethod(crossx_class, (t_method)crossx_dsp, gensym("dsp"), 0); class_addmethod(crossx_class, (t_method)crossx_assist, gensym("assist"), 0); class_addmethod(crossx_class, (t_method)crossx_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(crossx_class, (t_method)crossx_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(crossx_class, (t_method)crossx_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(crossx_class, (t_method)crossx_fftinfo, gensym("fftinfo"), 0); class_addmethod(crossx_class, (t_method)crossx_autonorm, gensym("autonorm"), A_DEFFLOAT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void crossx_autonorm(t_crossx *x, t_floatarg toggle) { x->autonorm = (short) toggle; } void crossx_assist (t_crossx *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Driver Sound"); break; case 1: sprintf(dst,"(signal) Filter Sound"); break; case 2: sprintf(dst,"(float/signal) Cross Synthesis Threshold"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void crossx_overlap(t_crossx *x, t_floatarg o) { if(!fftease_power_of_two((int)o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; crossx_init(x,1); } void crossx_winfac(t_crossx *x, t_floatarg f) { if(!fftease_power_of_two((int)f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; crossx_init(x,1); } void crossx_fftinfo( t_crossx *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void crossx_mute(t_crossx *x, t_floatarg toggle) { x->mute = (short)toggle; } void crossx_free(t_crossx *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input1,0); freebytes(x->input2,0); freebytes(x->Hwin,0); freebytes(x->buffer1,0); freebytes(x->buffer2,0); freebytes(x->channel1,0); freebytes(x->channel2,0); freebytes(x->output,0); /* these last are extra - kill if we clean up - upstairs free(x->c_lastphase_in1); free(x->c_lastphase_in2); free(x->c_lastphase_out); free(x->last_channel);*/ } #if MSP void crossx_float(t_crossx *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 2) { x->threshie = f; } } #endif void *crossx_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_crossx *x = (t_crossx *)newobject(crossx_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_crossx *x = (t_crossx *)pd_new(crossx_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(x->overlap <= 0) x->overlap = 4; x->winfac = 1; x->R = sys_getsr(); x->vs = sys_getblksize(); crossx_init(x,0); return (x); } void crossx_init(t_crossx *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->threshie = .001 ; x->autonorm = 0; x->mute = 0; x->Wanal = (float *) getbytes((MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes((MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes((MAX_Nw) * sizeof(float)); x->output = (float *) getbytes((MAX_Nw) * sizeof(float)); x->bitshuffle = (int *) getbytes((MAX_N * 2)* sizeof(int)); x->trigland = (float *) getbytes((MAX_N * 2)* sizeof(float)); x->input1 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer1 = (float *) getbytes(MAX_N * sizeof(float)); x->channel1 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->input2 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer2 = (float *) getbytes(MAX_N * sizeof(float)); x->channel2 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->last_channel = (float *) getbytes((MAX_N+2) * sizeof(float)); x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float)); } memset((char *)x->input1,0,x->Nw * sizeof(float)); memset((char *)x->input2,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer1,0,x->N * sizeof(float)); memset((char *)x->buffer2,0,x->N * sizeof(float)); memset((char *)x->channel1,0,(x->N+2) * sizeof(float)); memset((char *)x->channel2,0,(x->N+2) * sizeof(float)); memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } t_int *crossx_perform(t_int *w) { int i, j; float a1, a2, b1, b2; int even, odd; int amp, freq; float gainer, threshie; float ingain = 0; float outgain, rescale; float mymult; t_crossx *x = (t_crossx *) (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]); t_int n = w[6]; /* dereference struncture */ float *input1 = x->input1; float *input2 = x->input2; float *buffer1 = x->buffer1; float *buffer2 = x->buffer2; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *output = x->output; float *channel1 = x->channel1; float *channel2 = x->channel2; float *last_channel = x->last_channel; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; float *c_lastphase_in1 = x->c_lastphase_in1; float *c_lastphase_in2 = x->c_lastphase_in2; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; short autonorm = x->autonorm; if(x->mute){ while(n--){ *out++ = 0; } return w+7; } if( x->thresh_connected ){ threshie = *in3++; } else { threshie = x->threshie; } inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input1[j] = input1[j+D]; input2[j] = input2[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input1[j] = *in1++; input2[j] = *in2++; } fold( input1, Wanal, Nw, buffer1, N, inCount ); fold( input2, Wanal, Nw, buffer2, N, inCount ); rdft( N, 1, buffer1, bitshuffle, trigland ); rdft( N, 1, buffer2, bitshuffle, trigland ); /* changing algorithm for window flexibility */ if(autonorm){ ingain = 0; for(i = 0; i < N; i+=2){ ingain += hypot(buffer1[i], buffer1[i+1]); } } for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(buffer1+1) : *(buffer1+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(buffer1+odd) ); a2 = ( i == N2 ? *(buffer2+1) : *(buffer2+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(buffer2+odd) ); gainer = hypot(a2, b2); if( gainer > threshie ) *(channel1+even) = hypot( a1, b1 ) * gainer; *(channel1+odd) = -atan2( b1, a1 ); *(buffer1+even) = *(channel1+even) * cos( *(channel1+odd) ); if ( i != N2 ) *(buffer1+odd) = -(*(channel1+even)) * sin( *(channel1+odd) ); } if(autonorm){ outgain = 0; for(i = 0; i < N; i+=2){ outgain += hypot(buffer1[i], buffer1[i+1]); } if(ingain <= .0000001){ // post("gain emergency!"); rescale = 1.0; } else { rescale = ingain / outgain; } // post("ingain %f outgain %f rescale %f",ingain, outgain, rescale); mymult = mult * rescale; } else { mymult = mult; } rdft( N, -1, buffer1, bitshuffle, trigland ); overlapadd( buffer1, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mymult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void crossx_dsp(t_crossx *x, t_signal **sp, short *count) { #if MSP x->thresh_connected = count[2]; #endif #if PD x->thresh_connected = 1; #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr ){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; crossx_init(x,1); } dsp_add(crossx_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/dentist~-help.pd0000644000076500007650000000656612067450034016351 0ustar hanshans#N canvas 71 582 526 376 10; #N canvas 0 22 482 332 dentist-block 0; #X obj 322 150 block~ 256; #X obj 185 65 inlet~; #X obj 257 67 inlet; #X obj 185 174 outlet~; #X obj 221 264 snapshot~; #X obj 199 229 metro 80; #X msg 201 204 1; #X obj 310 287 outlet; #X obj 84 188 loadbang; #X obj 185 112 dentist~ 8000; #X obj 271 218 s dentist-stored-teeth; #X connect 1 0 9 0; #X connect 2 0 9 0; #X connect 4 0 7 0; #X connect 5 0 4 0; #X connect 6 0 5 0; #X connect 8 0 6 0; #X connect 9 0 3 0; #X connect 9 1 4 0; #X connect 9 2 10 0; #X restore 126 106 pd dentist-block; #X msg 263 173 \; pd dsp \$1; #X obj 263 147 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 126 180 dac~; #N canvas 639 41 688 619 messages 0; #X obj 70 447 outlet; #X msg 271 50 ramptime \$1; #X obj 271 26 nbx 5 14 -1e+37 1e+37 0 0 empty empty empty 0 -6 0 10 -262144 -1 -1 1000 256; #X msg 271 4 1000; #X obj 271 -17 loadbang; #X msg 186 431 toothcount \$1; #X msg 95 234 topfreq \$1; #X floatatom 95 212 5 0 0 0 - - -; #X text 94 196 highest frequency for bin selection; #X text 330 26 interpolation time between distributions; #X text 89 57 set distribution; #X msg 330 330 interpolate_singles \$1; #X obj 330 303 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X msg 70 75 scramble; #X obj 299 430 hsl 128 15 0 127 0 0 toothcount empty toothcount -2 -6 0 8 -85171 -1 -1 5300 1; #X text 220 448 this sets the number of bins within a fixed random distribution. must be greater than zero to hear sound.; #X obj 70 487 fftease-system; #X msg 186 389 10; #N canvas 643 146 878 628 data-storage 0; #X obj 260 105 outlet; #X msg 260 -66 setstate 30 31 32 33 34 35; #X msg 260 -49 setstate 7 9 11 13; #X text 250 -92 set a particular bin distribution; #X msg 260 -32 setstate 16 20 7 10 24 12 2 23 3; #X msg 260 64 showstate; #X text 337 64 list current bin selections; #X obj 80 140 r dentist-stored-teeth; #X obj 80 167 print; #X text 128 170 <- replace with [prepend set] -> [messagebox] if you have a "prepend" in your Pd distribution. Otherwise we just print to the Pd window.; #X text 241 141 <- from the dentist~ list outlet; #X connect 5 0 0 0; #X connect 7 0 8 0; #X restore 143 339 pd data-storage; #X obj 186 369 loadbang; #X obj 186 410 nbx 5 14 -1e+37 1e+37 0 0 empty toothcount empty 0 -6 0 12 -262144 -1 -1 50 256; #X obj 70 17 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 70 36 metro 1000; #X text 89 15 do it repeatedly; #X text 286 275 turn OFF to make toothcount changes instantaneous; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X connect 7 0 6 0; #X connect 11 0 0 0; #X connect 12 0 11 0; #X connect 13 0 0 0; #X connect 16 0 0 0; #X connect 17 0 20 0; #X connect 18 0 0 0; #X connect 19 0 17 0; #X connect 20 0 5 0; #X connect 21 0 22 0; #X connect 22 0 13 0; #X restore 233 80 pd messages; #X obj 126 150 *~ 2; #X obj 61 228 hsl 128 15 0 4 0 0 gain empty gain -2 -6 0 8 -208862 -1 -1 12700 1; #X text 316 81 <- open me; #X obj 126 66 noise~; #X floatatom 233 131 5 0 0 0 - - -; #X text 279 131 sync; #X text 72 272 dentist~ punches out all but a select set of partials. The argument is the maximum frequency from which to select partials. ; #X floatatom 149 130 5 0 0 0 - gain -; #X connect 0 0 5 0; #X connect 0 1 9 0; #X connect 2 0 1 0; #X connect 4 0 0 1; #X connect 5 0 3 0; #X connect 5 0 3 1; #X connect 8 0 0 0; #X connect 12 0 5 1; fftease-2.5.2.git20121005/dentist~.c0000644000076500007650000004360312067450034015233 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *dentist_class; #endif #if PD static t_class *dentist_class; #endif #define OBJECT_NAME "dentist~" typedef struct _dentist { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // short *bin_selection; short *last_bin_selection; int *active_bins; int tooth_count; int ramp_frames; int frames_left; float frame_duration; int max_bin; // float mult; float *trigland; int *bitshuffle; int overlap; int winfac; float topfreq; float funda; // void *list_outlet; short direct_update; short mute; t_atom *list_data; short interpolate_singles; float sync; } t_dentist; void *dentist_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *dentist_perform(t_int *w); void dentist_dsp(t_dentist *x, t_signal **sp, short *count); void dentist_assist(t_dentist *x, void *b, long m, long a, char *s); void set_switch_bins (t_dentist *x, int i); void reset_shuffle(t_dentist *x); void dentist_showstate(t_dentist *x); void dentist_direct_update(t_dentist *x, t_floatarg toggle); void dentist_mute(t_dentist *x, t_floatarg toggle); void dentist_setstate(t_dentist *x, t_symbol *msg, short argc, t_atom *argv); void dentist_ramptime(t_dentist *x, t_floatarg ramp_ms); int rand_index(int max); void dentist_init(t_dentist *x, short initialized); void dentist_bins_pd (t_dentist *x, t_floatarg i); void dentist_topfreq(t_dentist *x, t_floatarg f); void dentist_free(t_dentist *x); void dentist_toothcount(t_dentist *x, t_floatarg newcount); void dentist_scramble(t_dentist *x); void dentist_activate_bins(t_dentist *x, t_floatarg f); void dentist_interpolate_singles(t_dentist *x, t_floatarg f); void dentist_overlap(t_dentist *x, t_floatarg o); void dentist_winfac(t_dentist *x, t_floatarg o); void dentist_fftinfo(t_dentist *x); void dentist_mute(t_dentist *x, t_floatarg toggle); #if MSP void main(void) { setup((t_messlist **)&dentist_class, (method)dentist_new, (method)dsp_free, (short)sizeof(t_dentist), 0, A_GIMME, 0); addmess((method)dentist_dsp, "dsp", A_CANT, 0); addint((method)set_switch_bins); // addbang((method)reset_shuffle); addmess((method)dentist_showstate,"showstate",0); // addmess((method)dentist_direct_update,"direct_update",A_FLOAT, 0); addmess((method)dentist_mute,"mute",A_FLOAT, 0); addmess((method)dentist_setstate, "setstate", A_GIMME, 0); addmess((method)dentist_ramptime, "ramptime", A_FLOAT, 0); addmess((method)dentist_topfreq, "topfreq", A_FLOAT, 0); addmess((method)dentist_toothcount, "toothcount", A_FLOAT, 0); // addmess((method)dentist_activate_bins, "activate_bins", A_FLOAT, 0); addmess((method)dentist_interpolate_singles, "interpolate_singles", A_FLOAT, 0); addmess((method)dentist_scramble, "scramble", 0); addmess((method)dentist_assist,"assist",A_CANT,0); addmess((method)dentist_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)dentist_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)dentist_fftinfo, "fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void dentist_tilde_setup(void) { dentist_class = class_new(gensym("dentist~"), (t_newmethod)dentist_new, (t_method)dentist_free ,sizeof(t_dentist), 0,A_GIMME,0); CLASS_MAINSIGNALIN(dentist_class, t_dentist, x_f); class_addmethod(dentist_class,(t_method)dentist_dsp,gensym("dsp"),0); class_addmethod(dentist_class,(t_method)dentist_mute,gensym("mute"),A_FLOAT,0); class_addmethod(dentist_class,(t_method)dentist_showstate,gensym("showstate"),0); // class_addmethod(dentist_class,(t_method)dentist_direct_update,gensym("direct_update"),A_FLOAT,0); class_addmethod(dentist_class,(t_method)dentist_setstate,gensym("setstate"),A_GIMME,0); class_addmethod(dentist_class,(t_method)dentist_ramptime,gensym("ramptime"),A_FLOAT,0); // class_addmethod(dentist_class,(t_method)dentist_bins_pd,gensym("dentist_bins"),A_FLOAT,0); class_addmethod(dentist_class,(t_method)dentist_topfreq,gensym("topfreq"),A_FLOAT,0); class_addmethod(dentist_class,(t_method)dentist_toothcount,gensym("toothcount"),A_FLOAT,0); class_addmethod(dentist_class,(t_method)dentist_interpolate_singles,gensym("interpolate_singles"),A_FLOAT, 0); class_addmethod(dentist_class,(t_method)dentist_scramble,gensym("scramble"),0); // class_addmethod(dentist_class,(t_method)dentist_activate_bins,gensym("activate_bins"),A_FLOAT,0); class_addmethod(dentist_class, (t_method)dentist_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(dentist_class, (t_method)dentist_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(dentist_class, (t_method)dentist_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void dentist_interpolate_singles(t_dentist *x, t_floatarg f) { x->interpolate_singles = (short)f; // post("singles interp: %d",x->interpolate_singles); } void dentist_free(t_dentist *x) { /* Pd might be having difficulty freeing its memory */ #if MSP dsp_free((t_pxobject *)x); #endif free(x->Wanal); free(x->Wsyn); free(x->input); free(x->Hwin); free(x->buffer); free(x->channel); free(x->output); free(x->bitshuffle); free(x->trigland); free(x->bin_selection); free(x->active_bins); free(x->last_bin_selection); free(x->list_data); //post("avoiding freeing memory here"); } void dentist_overlap(t_dentist *x, t_floatarg f) { int o = (int)f; if(!fftease_power_of_two(o)){ error("%d is not a power of two",o); return; } x->overlap = o; dentist_init(x,1); } void dentist_winfac(t_dentist *x, t_floatarg f) { int w = (int)f; if(!fftease_power_of_two(w)){ error("%d is not a power of two",w); return; } x->winfac = w; dentist_init(x,2); } void dentist_fftinfo( t_dentist *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void dentist_direct_update( t_dentist *x, t_floatarg toggle) { x->direct_update = (short)toggle; } void dentist_mute( t_dentist *x, t_floatarg toggle ) { x->mute = (short)toggle; } void dentist_assist (t_dentist *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input "); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"(signal) Output"); break; case 1: sprintf(dst,"(signal) Interpolation Sync"); break; case 2: sprintf(dst,"(list) Current Selected Bins"); break; } } } void *dentist_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_dentist *x = (t_dentist *)newobject(dentist_class); x->list_outlet = listout((t_pxobject *)x); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_dentist *x = (t_dentist *)pd_new(dentist_class); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); x->list_outlet = outlet_new(&x->x_obj,gensym("list")); #endif // INITIALIZATIONS x->D = sys_getblksize(); x->R = sys_getsr(); x->topfreq = atom_getfloatarg(0,argc,argv); x->overlap = atom_getfloatarg(1,argc,argv); x->winfac = atom_getfloatarg(2,argc,argv); if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; dentist_init(x,0); return (x); } void dentist_topfreq(t_dentist *x, t_floatarg f) { float funda = x->funda; float curfreq; if(f < 50 || f > x->R/2.0) return; x->topfreq = f; x->max_bin = 1; curfreq = 0; while(curfreq < x->topfreq) { ++(x->max_bin); curfreq += funda ; } } void dentist_init(t_dentist *x, short initialized) { float curfreq; int i; x->N = x->overlap * x->D; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); if(!initialized){ x->sync = 0; x->mute = 0; x->direct_update = 0; if(x->topfreq < 100) x->topfreq = 100.0; x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->input = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->buffer = (float *) calloc(MAX_N, sizeof(float)); x->channel = (float *) calloc(MAX_N+2, sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); x->bin_selection = (short *) calloc( MAX_N2, sizeof(short)); x->active_bins = (int *) calloc( MAX_N2, sizeof(int)); x->last_bin_selection = (short *) calloc( MAX_N2, sizeof(short)) ; x->list_data = (t_atom *) calloc( MAX_N + 2, sizeof(t_atom)); x->tooth_count = 0; x->interpolate_singles = 1; x->ramp_frames = 0; dentist_scramble(x); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->channel,0,(x->N+2) * sizeof(float)); x->mult = 1. / (float) x->N; x->frame_duration = (float) x->D / (float) x->R; x->frames_left = 0; x->funda = (float) x->R / (float) x->N; x->max_bin = 1; /* curfreq = 0; while(curfreq < x->topfreq) { ++(x->max_bin); curfreq += x->funda; }*/ if(!x->funda){ error("%s: zero sampling rate!",OBJECT_NAME); return; } x->max_bin = (int) (x->topfreq / x->funda); if(x->max_bin < 1) x->max_bin = 1; init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); for( i = 0; i < x->N2; i++) { x->last_bin_selection[i] = x->bin_selection[i]; } } t_int *dentist_perform(t_int *w) { int i,j; float oldfrac,newfrac; int tooth_count; t_dentist *x = (t_dentist *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); t_float *sync_vec = (t_float *)(w[4]); t_int n = w[5]; int frames_left = x->frames_left; int ramp_frames = x->ramp_frames; short *bin_selection = x->bin_selection; short *last_bin_selection = x->last_bin_selection; /* dereference struncture */ float *input = x->input; float *buffer = x->buffer; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *output = x->output; float *channel = x->channel; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float sync = x->sync; if( x->mute ){ while( n-- ){ *out++ = 0.0; *sync_vec++ = sync; } return (w+6); } inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); leanconvert( buffer, channel, N2 ); if(frames_left > 0 && ramp_frames > 0) { // INTERPOLATE ACCORDING TO POSITION IN RAMP oldfrac = (float) frames_left / (float) ramp_frames ; sync = newfrac = 1.0 - oldfrac; for( i = 0; i < N2 ; i++){ if( (! bin_selection[i]) && (! last_bin_selection[i]) ){ channel[i * 2] = 0; } else if (bin_selection[i] && last_bin_selection[i]) { // channel[i * 2] *= 1; NO ACTION } else if (bin_selection[i]) { channel[i * 2] *= newfrac; } else if (last_bin_selection[i]) { channel[i * 2] *= oldfrac; } } --frames_left; if( ! frames_left ){ // Copy current to last for( i = 0; i < N2; i++) { last_bin_selection[i] = bin_selection[i]; } } } else { for( i = 0; i < N2 ; i++){ if( ! bin_selection[ i ] ){ channel[ i * 2 ] = 0; } } oldfrac = 0.0; sync = 1.0; } leanunconvert( channel, buffer, N2 ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ for(i=0; i < n; i++){ sync_vec[i] = sync; } x->inCount = inCount % Nw; x->frames_left = frames_left; x->sync = sync; return (w+6); } void set_switch_bins (t_dentist *x, int i) { if( i < 0 ){ i = 0; } if( i > x->N2 ) { i = x->N2; } x->tooth_count = i; if( x->direct_update ){ reset_shuffle(x); } return; } //identical function for Pd void dentist_bins_pd (t_dentist *x, t_floatarg i) { if( i < 0 ){ i = 0; } if( i > x->N2 ) { i = x->N2; } x->tooth_count = (int)i; if(x->direct_update){ reset_shuffle(x); } return; } // experimental, not to be used void dentist_activate_bins(t_dentist *x, t_floatarg f) { if(f < 0 || f > x->max_bin){ #if PD post("* %d bin out of range",(int)f); #endif return; } x->tooth_count = (int)f; } void dentist_scramble(t_dentist *x) { short *last_bin_selection = x->last_bin_selection; short *bin_selection = x->bin_selection; int *active_bins = x->active_bins; int N2 = x->N2; int i,tmp,b1,b2; int maxswap = x->max_bin; int tooth_count = x->tooth_count; /* for(i = 0; i < x->N2; i++){ last_bin_selection[i] = bin_selection[i]; }*/ for(i=0; i 0){ b1 = maxswap; b2 = rand_index(maxswap); tmp = active_bins[b1]; active_bins[b1] = active_bins[b2]; active_bins[b2] = tmp; --maxswap; } for( i = 0; i < x->tooth_count; i++ ) { x->bin_selection[active_bins[i]] = 1; } x->frames_left = x->ramp_frames; if(! x->ramp_frames) { for(i = 0; i < N2; i++){ last_bin_selection[i] = bin_selection[i]; } } } void dentist_toothcount(t_dentist *x, t_floatarg newcount) { int i; int nc = (int) newcount; int max = x->max_bin; int tooth_count = x->tooth_count; int newbin; int oldbin; if(nc < 0 || nc > x->N2){ #if PD post("* %d out of range",nc); #endif #if MSP error("%d out of range",nc); #endif return; } /* for(i = 0; i < x->N2; i++){ x->last_bin_selection[i] = x->bin_selection[i]; }*/ if(nc < x->tooth_count){ for(i = nc; i < tooth_count; i++){ x->bin_selection[x->active_bins[i]] = 0; } } else { for(i = tooth_count; i < nc; i++){ x->bin_selection[x->active_bins[i]] = 1; } } // if immediate reset if(x->interpolate_singles){ // post("setting frames left"); x->frames_left = x->ramp_frames; } if(! x->ramp_frames) { for(i = 0; i < x->N2; i++){ x->last_bin_selection[i] = x->bin_selection[i]; } } x->tooth_count = nc; } void reset_shuffle (t_dentist *x) { int i; int temp, p1, p2; int max; max = x->max_bin; for(i = 0; i < x->N2; i++){ x->last_bin_selection[i] = x->bin_selection[i]; x->bin_selection[i] = 0; } for(i = 0; i < x->max_bin; i++) { x->active_bins[i] = rand_index(max); x->bin_selection[x->active_bins[i]] = 1; } x->frames_left = x->ramp_frames; if(! x->ramp_frames) { // Ramp Off - Immediately set last to current for( i = 0; i < x->N2; i++ ){ x->last_bin_selection[ i ] = x->bin_selection[ i ]; } } } int rand_index(int max) { return (rand() % max); } void dentist_setstate (t_dentist *x, t_symbol *msg, short argc, t_atom *argv) { short i; int selex; short *last_bin_selection = x->last_bin_selection; short *bin_selection = x->bin_selection; int *active_bins = x->active_bins; x->tooth_count = argc; for(i = 0; i < x->N2; i++){ last_bin_selection[i] = bin_selection[i]; // needed here bin_selection[i] = 0; } for (i=0; i < argc; i++) { selex = atom_getfloatarg(i,argc,argv); if (selex < x->N2 && selex >= 0 ) { active_bins[i] = selex; bin_selection[selex] = 1; } else { post ("%d out of range bin",selex); } } x->frames_left = x->ramp_frames; if(! x->ramp_frames) { // Ramp Off - Immediately set last to current for(i = 0; i < x->N2; i++){ last_bin_selection[i] = bin_selection[i]; } } return; } void dentist_ramptime (t_dentist *x, t_floatarg ramp_ms) { if(ramp_ms <= 0){ x->ramp_frames = 0; return; } x->frames_left = x->ramp_frames = (int)(ramp_ms * .001 / x->frame_duration); return; } // REPORT CURRENT SHUFFLE STATUS void dentist_showstate (t_dentist *x) { t_atom *list_data = x->list_data; short i, count; float data; count = 0; for(i = 0; i < x->tooth_count; i++ ) { data = x->active_bins[i]; #if MSP SETLONG(list_data+count,x->active_bins[i]); #endif #if PD SETFLOAT(list_data+count,data); #endif ++count; } outlet_list(x->list_outlet,0,x->tooth_count,list_data); return; } void dentist_dsp(t_dentist *x, t_signal **sp, short *count) { long i; if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; dentist_init(x,1); } dsp_add(dentist_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/disarrain~-help.pd0000644000076500007650000000617112067450034016643 0ustar hanshans#N canvas 717 430 516 403 10; #N canvas 1009 566 462 312 disarrain-block 0; #X obj 137 111 disarrain~ 4000; #X obj 137 177 outlet~; #X obj 237 173 outlet; #X obj 137 66 inlet~; #X obj 53 247 block~ 256; #X obj 205 217 snapshot~; #X obj 324 189 metro 100; #X msg 325 162 1; #X obj 327 125 loadbang; #X obj 205 242 outlet; #X obj 316 74 inlet; #X connect 0 0 1 0; #X connect 0 1 5 0; #X connect 0 2 2 0; #X connect 3 0 0 0; #X connect 5 0 9 0; #X connect 6 0 5 0; #X connect 7 0 6 0; #X connect 8 0 7 0; #X connect 10 0 0 0; #X restore 63 80 pd disarrain-block; #X obj 63 11 phasor~ 174; #X obj 63 241 *~ 0.05; #X floatatom 123 132 5 0 0 0 - - -; #X obj 63 286 dac~; #X obj 110 199 hsl 128 15 0 0.5 0 0 empty empty empty -2 -6 0 8 -258444 -1 -1 3000 1; #X floatatom 107 220 5 0 0 0 - - -; #X msg 285 258 \; pd dsp \$1; #X obj 285 237 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 51 333 disarrain~ is a modified version of disarray~ that interpolates between different spectral reorderings.; #N canvas 476 454 458 308 messages 0; #X obj 209 234 outlet; #X obj 303 202 fftease-system; #N canvas 904 74 603 462 main-messages 0; #X obj 8 407 outlet; #X floatatom 38 65 5 0 0 0 - - -; #X msg 77 148 forcefade \$1; #X obj 78 122 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X floatatom 99 216 5 0 0 0 - - -; #X msg 99 242 fadetime \$1; #X floatatom 218 283 5 0 0 0 - - -; #X msg 218 309 topfreq \$1; #X msg 195 391 killfade; #X msg 38 91 switch_count \$1; #X msg 8 28 reset_shuffle; #X text 123 29 make new reordering; #X text 153 93 number of bins to reorder (at 0 there is no bin swapping) ; #X text 167 151 permit override of current fade for instantaneous changes ; #X text 297 312 top frequency to be shuffled; #X text 270 391 immediately end current crossfade; #X text 195 241 crossfade interpolation time; #X msg 99 194 3000; #X obj 99 172 loadbang; #X connect 1 0 9 0; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 5 0; #X connect 5 0 0 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 17 0 4 0; #X connect 18 0 17 0; #X restore 31 31 pd main-messages; #N canvas 752 371 590 315 data 0; #X obj 89 237 outlet; #X msg 48 83 isetstate 73 109 187 113 3 2 1 30 96 4 7; #X msg 105 119 setstate 0 20 23 42 2 18 6 7 38 14 10 27 12 8 4 19 16 5 36 9 15 40 39 45 24 25 28 17 33 13 43 29 34 21 32 35 22 37 46 1 26 3 41 44 11 31 30 47 48 49; #X text 138 160 instant recall; #X text 51 67 recall a mapping you like; #X msg 194 188 showstate; #X text 269 189 output current remapping as a list; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 5 0 0 0; #X restore 5 145 pd data; #X text 151 32 <- now go here; #X text 58 144 <- if you find a setting you like and wish to store it; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 0 0; #X restore 184 53 pd messages; #X obj 184 111 print; #X text 229 113 prints current reordering; #X text 124 146 crossfade sync; #X text 277 56 <- start here; #X connect 0 0 2 0; #X connect 0 1 3 0; #X connect 0 2 11 0; #X connect 1 0 0 0; #X connect 2 0 4 0; #X connect 2 0 4 1; #X connect 5 0 6 0; #X connect 6 0 2 1; #X connect 8 0 7 0; #X connect 10 0 0 1; fftease-2.5.2.git20121005/disarrain~.c0000644000076500007650000005550312067450034015537 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *disarrain_class; #endif #if PD static t_class *disarrain_class; #endif #define OBJECT_NAME "disarrain~" typedef struct _disarrain { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *last_channel; float *composite_channel; float *output; int overlap; int winfac; // int *shuffle_mapping; int *last_shuffle_mapping; int *shuffle_tmp; // work space for making a new distribution int shuffle_count;// number of bins to swap int last_shuffle_count;// ditto from last shuffle mapping int max_bin; // float mult; float *trigland; int *bitshuffle; // void *list_outlet; t_atom *list_data; short mute; short bypass; float frame_duration; // duration in seconds of a single frame float interpolation_duration; // duration in seconds of interpolation int interpolation_frames; // number of frames to interpolate int frame_countdown; // keep track of position in interpolation int overlap_factor;// determines window size, etc. float top_frequency;// for remapping spectrum int perform_method;// 0 for lean, 1 for full conversion // for convert // float *c_lastphase_in; // float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // check switching algorithm short lock;// lock for switching mapping arrays, but not used now short force_fade; // new fadetime set regardless of situation short force_switch;// binds new distribution to change of bin count } t_disarrain; void *disarrain_new(t_symbol *msg, short argc, t_atom *argv); t_int *disarrain_perform_lean(t_int *w); t_int *disarrain_perform_full(t_int *w); void disarrain_dsp(t_disarrain *x, t_signal **sp, short *count); void disarrain_assist(t_disarrain *x, void *b, long m, long a, char *s); void disarrain_switch_count (t_disarrain *x, t_floatarg i); void disarrain_topfreq (t_disarrain *x, t_floatarg freq); void disarrain_fadetime (t_disarrain *x, t_floatarg f); void reset_shuffle( t_disarrain *x ); void disarrain_showstate( t_disarrain *x ); void disarrain_list (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv); void disarrain_setstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv); void disarrain_isetstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv); int rand_index(int max); void disarrain_mute(t_disarrain *x, t_floatarg toggle); void disarrain_bypass(t_disarrain *x, t_floatarg toggle); void copy_shuffle_array(t_disarrain *x); void interpolate_frames_to_channel(t_disarrain *x); void disarrain_killfade(t_disarrain *x); void disarrain_forcefade(t_disarrain *x, t_floatarg toggle); void disarrain_init(t_disarrain *x, short initialized); void disarrain_free(t_disarrain *x); void disarrain_overlap(t_disarrain *x, t_floatarg o); void disarrain_winfac(t_disarrain *x, t_floatarg o); void disarrain_fftinfo(t_disarrain *x); void disarrain_force_switch(t_disarrain *x, t_floatarg toggle); #if MSP void main(void) { setup((t_messlist **)&disarrain_class, (method)disarrain_new, (method)disarrain_free, (short)sizeof(t_disarrain), 0, A_GIMME, 0); addmess((method)disarrain_dsp, "dsp", A_CANT, 0); addint((method)disarrain_switch_count); addbang((method)reset_shuffle); addmess((method)disarrain_showstate,"showstate",0); addmess ((method)disarrain_list, "list", A_GIMME, 0); addmess ((method)disarrain_setstate, "setstate", A_GIMME, 0); addmess ((method)disarrain_isetstate, "isetstate", A_GIMME, 0); addmess((method)disarrain_assist,"assist",A_CANT,0); addmess ((method)disarrain_mute, "mute", A_FLOAT, 0); addmess ((method)disarrain_topfreq, "topfreq", A_FLOAT, 0); addmess ((method)disarrain_fadetime, "fadetime", A_FLOAT, 0); addmess ((method)disarrain_bypass, "bypass", A_FLOAT, 0); addmess ((method)disarrain_forcefade, "forcefade", A_FLOAT, 0); addmess ((method)disarrain_force_switch, "force_switch", A_FLOAT, 0); addmess ((method)disarrain_switch_count, "switch_count", A_FLOAT, 0); addmess ((method)disarrain_killfade, "killfade", 0); addmess ((method)reset_shuffle, "reset_shuffle", 0); addmess((method)disarrain_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)disarrain_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)disarrain_fftinfo, "fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void disarrain_tilde_setup(void) { disarrain_class = class_new(gensym("disarrain~"), (t_newmethod)disarrain_new, (t_method)disarrain_free ,sizeof(t_disarrain), 0,A_GIMME,0); CLASS_MAINSIGNALIN(disarrain_class, t_disarrain, x_f); class_addmethod(disarrain_class, (t_method)disarrain_dsp, gensym("dsp"), 0); class_addmethod(disarrain_class, (t_method)disarrain_showstate, gensym("showstate"), 0); class_addmethod(disarrain_class, (t_method)disarrain_list, gensym("list"), A_GIMME, 0); class_addmethod(disarrain_class, (t_method)disarrain_setstate, gensym("setstate"), A_GIMME, 0); class_addmethod(disarrain_class, (t_method)disarrain_isetstate, gensym("isetstate"), A_GIMME, 0); class_addmethod(disarrain_class, (t_method)disarrain_mute, gensym("mute"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_topfreq, gensym("topfreq"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_fadetime, gensym("fadetime"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_bypass, gensym("bypass"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_forcefade, gensym("forcefade"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_force_switch, gensym("force_switch"), A_FLOAT, 0); // class_addmethod(disarrain_class, (t_method)disarrain_killfade, gensym("reset"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)reset_shuffle, gensym("bang"), 0); class_addmethod(disarrain_class, (t_method)reset_shuffle, gensym("reset_shuffle"), 0); class_addmethod(disarrain_class, (t_method)disarrain_switch_count, gensym("switch_count"), A_FLOAT, 0); class_addmethod(disarrain_class, (t_method)disarrain_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(disarrain_class, (t_method)disarrain_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(disarrain_class, (t_method)disarrain_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void disarrain_free(t_disarrain *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->Wanal, x->Nw * sizeof(float)); freebytes(x->Wsyn, x->Nw * sizeof(float)); freebytes(x->input, x->Nw * sizeof(float)); freebytes(x->Hwin, x->Nw * sizeof(float)); freebytes(x->buffer, x->N * sizeof(float)); freebytes(x->channel, (x->N+2) * sizeof(float)); freebytes(x->last_channel, (x->N+2) * sizeof(float)); freebytes(x->composite_channel, x->N+2 * sizeof(float)); freebytes(x->output, x->Nw * sizeof(float)); freebytes(x->bitshuffle, (x->N * 2) * sizeof(int)); freebytes(x->trigland, x->N * 2 * sizeof(float)); freebytes(x->shuffle_mapping, x->N2 * sizeof(int)) ; freebytes(x->last_shuffle_mapping, x->N2 * sizeof(int)) ; freebytes(x->shuffle_tmp, x->N2 * sizeof(int)) ; freebytes(x->list_data,(x->N+2) * sizeof(t_atom)) ; // freebytes(x->c_lastphase_in, (x->N2+1)*sizeof(float)); // freebytes(x->c_lastphase_out,(x->N2+1)* sizeof(float)); } void disarrain_init(t_disarrain *x, short initialized) { int i; float curfreq; if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->c_fundamental = (float) x->R/(float)( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->lock = 1; // not good enough if(initialized == 0){ x->Wanal = (float *) calloc(MAX_Nw , sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw , sizeof(float)); x->input = (float *) calloc(MAX_Nw , sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw , sizeof(float)); x->buffer = (float *) calloc(MAX_N , sizeof(float)); x->channel = (float *) calloc(MAX_N+2 , sizeof(float)); x->last_channel = (float *) calloc(MAX_N+2 , sizeof(float)); x->composite_channel = (float *) calloc(MAX_N+2 , sizeof(float)); x->output = (float *) calloc(MAX_Nw , sizeof(float)); x->bitshuffle = (int *) calloc((MAX_N * 2) , sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2 , sizeof(float)); x->shuffle_mapping = (int *) calloc( MAX_N2 , sizeof(int) ) ; x->last_shuffle_mapping = (int *) calloc( MAX_N2 , sizeof(int) ) ; x->shuffle_tmp = (int *) calloc( MAX_N2 , sizeof(int) ) ; x->list_data = (t_atom *) calloc((MAX_N+2) , sizeof(t_atom) ) ; x->mute = 0; x->bypass = 0; x->force_fade = 0; x->interpolation_duration = 0.1; //seconds } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->channel,0,(x->N+2) * sizeof(float)); memset((char *)x->last_channel,0,(x->N+2) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); if(initialized != 2){ if( x->top_frequency < x->c_fundamental || x->top_frequency > 20000) { x->top_frequency = 1000.0 ; } x->max_bin = 1; curfreq = 0; while( curfreq < x->top_frequency ) { ++(x->max_bin); curfreq += x->c_fundamental ; } for( i = 0; i < x->N2; i++ ) { x->shuffle_mapping[i] = x->last_shuffle_mapping[i] = i*2; } reset_shuffle(x); // set shuffle lookup copy_shuffle_array(x);// copy it to the last lookup (for interpolation) x->frame_duration = (float) x->D / (float) x->R; x->interpolation_frames = x->interpolation_duration / x->frame_duration; x->frame_countdown = 0; x->shuffle_count = 0; x->last_shuffle_count = 0; } x->lock = 0; } void disarrain_force_switch(t_disarrain *x, t_floatarg f) { x->force_switch = (short)f; } void disarrain_fadetime (t_disarrain *x, t_floatarg f) { int frames; float duration; // forcefade allows forcing new fadetime at any time if(! x->force_fade) { #if MSP if(!sys_getdspstate()){ return; // DSP is inactive } #endif if(x->frame_countdown) { error("disarrain: fade in progress, fadetime reset blocked"); return; } } duration = f * .001; frames = duration / x->frame_duration; if( frames <= 1){ error("%s: too short fade",OBJECT_NAME); return; } x->interpolation_duration = f * .001; x->interpolation_frames = frames; } void disarrain_killfade(t_disarrain *x) { x->frame_countdown = 0; } void disarrain_topfreq (t_disarrain *x, t_floatarg freq) { float funda = (float) x->R / (2. * (float) x->N) ; float curfreq; if( freq < funda || freq > 20000) { freq = 1000.0 ; } x->max_bin = 1; curfreq = 0; while( curfreq < freq ) { ++(x->max_bin); curfreq += funda ; } } void disarrain_assist (t_disarrain *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"(signal) Output"); break; case 1: sprintf(dst,"(signal) Interpolation Sync"); break; case 2: sprintf(dst,"(list) Current State"); break; } } } void *disarrain_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_disarrain *x = (t_disarrain *)newobject(disarrain_class); x->list_outlet = listout((t_pxobject *)x); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_disarrain *x = (t_disarrain *)pd_new(disarrain_class); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); x->list_outlet = outlet_new(&x->x_obj,gensym("list")); #endif srand(time(0)); x->D = sys_getblksize(); x->R = sys_getsr(); x->top_frequency = atom_getfloatarg(0,argc,argv); x->overlap_factor = atom_getintarg(1,argc,argv); x->winfac = atom_getintarg(2,argc,argv); disarrain_init(x,0); return (x); } void disarrain_forcefade(t_disarrain *x, t_floatarg toggle) { x->force_fade = (short)toggle; } void disarrain_mute(t_disarrain *x, t_floatarg toggle) { x->mute = (short)toggle; } void disarrain_bypass(t_disarrain *x, t_floatarg toggle) { x->bypass = (short)toggle; } void disarrain_overlap(t_disarrain *x, t_floatarg df) { int o = (int)df; if(!fftease_power_of_two(o)){ error("%d is not a power of two",o); return; } x->overlap = (int)o; disarrain_init(x,1); } void disarrain_winfac(t_disarrain *x, t_floatarg f) { int wf = (int)f; if(!fftease_power_of_two(wf)){ error("%f is not a power of two",wf); return; } x->winfac = wf; disarrain_init(x,2); /* calling lighter reinit routine */ } void disarrain_fftinfo( t_disarrain *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } // lean convert perform method t_int *disarrain_perform_lean(t_int *w) { t_disarrain *x = (t_disarrain *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); t_float *vec_sync = (t_float *)(w[4]); int n = w[5]; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *Hwin = x->Hwin; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float *last_channel = x->last_channel; int i,j; int inCount = x->inCount; int D = x->D; float tmp; float ival = 0.0; int *shuffle_mapping = x->shuffle_mapping; int shuffle_count = x->shuffle_count; int *last_shuffle_mapping = x->last_shuffle_mapping; int last_shuffle_count = x->last_shuffle_count; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; int frame_countdown = x->frame_countdown; // will read from variable int interpolation_frames = x->interpolation_frames; if( x->mute || x->lock ){ while( n-- ){ *out++ = 0.0; } return (w+6); } if( x->bypass ){ while( n-- ){ *out++ = *in++ * 0.5; // gain compensation } return (w+6); } inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold(input, Wanal, Nw, buffer, N, inCount); rdft(N, 1, buffer, bitshuffle, trigland); leanconvert(buffer, channel, N2); // first time for interpolation, just do last frame if(frame_countdown == interpolation_frames){ for( i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){ tmp = channel[j]; channel[j] = channel[last_shuffle_mapping[i]]; channel[last_shuffle_mapping[i]] = tmp; } --frame_countdown; } else if( frame_countdown > 0 ){ ival = (float)frame_countdown/(float)interpolation_frames; // copy current frame to lastframe for(j = 0; j < N; j+=2){ last_channel[j] = channel[j]; } // make last frame swap for(i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){ tmp = last_channel[j]; last_channel[j] = last_channel[last_shuffle_mapping[i]]; last_channel[last_shuffle_mapping[i]] = tmp; } // make current frame swap for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){ tmp = channel[j]; channel[j] = channel[shuffle_mapping[i]]; channel[shuffle_mapping[i]] = tmp; } // now interpolate between the two for(j = 0; j < N; j+=2){ channel[j] = channel[j] + ival * (last_channel[j] - channel[j]); } --frame_countdown; if(frame_countdown <= 0){ copy_shuffle_array(x); } } else { // otherwise straight swapping for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){ tmp = channel[j]; channel[j] = channel[ shuffle_mapping[i]]; channel[shuffle_mapping[i]] = tmp; } } leanunconvert( channel, buffer, N2 ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* send out sync signal */ for(j = 0; j < n; j++){ vec_sync[j] = ival; } /* restore state variables */ x->inCount = inCount % Nw; x->frame_countdown = frame_countdown; return (w+6); } void interpolate_frames_to_channel(t_disarrain *x) { float ival; float tmp; int i,j; int frame_countdown = x->frame_countdown; int interpolation_frames = x->interpolation_frames; float *channel = x->channel; float *last_channel = x->last_channel; int *shuffle_mapping = x->shuffle_mapping; int shuffle_count = x->shuffle_count; int *last_shuffle_mapping = x->shuffle_mapping; int last_shuffle_count = x->shuffle_count; int local_max_bins; int N = x->N; ival = (float)frame_countdown/(float)interpolation_frames; // post("interpolation:%f",ival); local_max_bins = (shuffle_count > last_shuffle_count)? shuffle_count : last_shuffle_count; // copy channel (only amplitudes) for(j = 0; j < N; j+=2){ last_channel[j] = channel[j]; } // make last frame for( i = 0, j = 0; i < last_shuffle_count ; i++, j+=2){ tmp = last_channel[j]; last_channel[j] = last_channel[last_shuffle_mapping[i]]; last_channel[last_shuffle_mapping[i]] = tmp; } // make current frame for( i = 0, j = 0; i < shuffle_count ; i++, j+=2){ tmp = channel[j]; channel[j] = channel[shuffle_mapping[i]]; channel[shuffle_mapping[i]] = tmp; } // now interpolate between the two for(j = 0; j < N; j+=2){ // channel[j] = channel[j] + ival * (last_channel[j] - channel[j]); // or better? channel[j] += ival * (last_channel[j] - channel[j]); } } void disarrain_switch_count (t_disarrain *x, t_floatarg f) { int i = f; /* #if MSP if(! sys_getdspstate()){ return; // DSP is inactive } #endif */ if( x->frame_countdown && !x->force_fade){ error("%s: fade in progress, no action taken",OBJECT_NAME); return; } if( i < 0 ){ i = 0; } if( i > x->N2 ) { i = x->N2; } copy_shuffle_array(x); x->last_shuffle_count = x->shuffle_count; x->shuffle_count = i; x->frame_countdown = x->interpolation_frames; // force interpolation } void reset_shuffle (t_disarrain *x) { int i; int temp, p1, p2; int max = x->max_bin; int N2 = x->N2; int *shuffle_tmp = x->shuffle_tmp; int *shuffle_mapping = x->shuffle_mapping; copy_shuffle_array(x); for( i = 0; i < N2; i++ ) { shuffle_tmp[i] = i; } // improve this algorithm for( i = 0; i < max; i++ ) { p1 = shuffle_tmp[ rand_index( max ) ]; p2 = shuffle_tmp[ rand_index( max ) ]; temp = shuffle_tmp[p1]; shuffle_tmp[ p1 ] = shuffle_tmp[ p2 ]; shuffle_tmp[ p2 ] = temp; } // now map to amplitude channels for( i = 0; i < N2; i++ ) { shuffle_tmp[i] *= 2; } // force interpolation x->frame_countdown = x->interpolation_frames; x->lock = 1; for( i = 0; i < N2; i++ ) { shuffle_mapping[i] = shuffle_tmp[i]; } x->lock = 0; } void copy_shuffle_array(t_disarrain *x) { int i; int N2 = x->N2; int *shuffle_mapping = x->shuffle_mapping; int *last_shuffle_mapping = x->last_shuffle_mapping; for(i = 0; ilast_shuffle_count = x->shuffle_count; } int rand_index(int max) { return (rand() % max); } void disarrain_dsp(t_disarrain *x, t_signal **sp, short *count) { long i; if(x->D != sp[0]->s_n ||x->D != sp[0]->s_n ) { x->R = sp[0]->s_sr; x->D = sp[0]->s_n; disarrain_init(x,1); } dsp_add(disarrain_perform_lean, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); } // ENTER STORED SHUFFLE void disarrain_list (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) { short i; int ival; // post("list message called"); x->shuffle_count = argc; // post("list: count now %d",x->shuffle_count ); for (i=0; i < argc; i++) { #if MSP ival = argv[i].a_w.w_long; #endif #if PD ival = atom_getfloatarg(i,argc,argv); #endif if (ival < x->N2) { x->shuffle_mapping[i] = ival; // post("set %d to %d",i, x->shuffle_mapping[ i ]); } else { // post ("%d out of range",ival); } } // post("last val is %d", x->shuffle_mapping[argc - 1]); return; } void disarrain_isetstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) { short i; int ival; // x->last_shuffle_count = x->shuffle_count; copy_shuffle_array(x); x->shuffle_count = argc; // x->lock = 1; for (i=0; i < argc; i++) { ival = 2 * atom_getfloatarg(i,argc,argv); if ( ival < x->N2 && ival >= 0) { x->shuffle_mapping[ i ] = ival; }else { error("%s: %d is out of range",OBJECT_NAME, ival); } } // x->lock = 0; x->frame_countdown = x->interpolation_frames; return; } void disarrain_setstate (t_disarrain *x, t_symbol *msg, short argc, t_atom *argv) { short i; int ival; x->shuffle_count = argc; for (i=0; i < argc; i++) { ival = 2 *atom_getfloatarg(i,argc,argv); if ( ival < x->N2 && ival >= 0) { x->shuffle_mapping[ i ] = ival; } else { error("%s: %d is out of range",OBJECT_NAME, ival); } } return; } // REPORT CURRENT SHUFFLE STATUS void disarrain_showstate (t_disarrain *x ) { t_atom *list_data = x->list_data; short i; #if MSP for( i = 0; i < x->shuffle_count; i++ ) { SETLONG(list_data+i,x->shuffle_mapping[i]/2); } #endif #if PD for( i = 0; i < x->shuffle_count; i++ ) { SETFLOAT(list_data+i,(float)x->shuffle_mapping[i]/2); } #endif outlet_list(x->list_outlet,0,x->shuffle_count,list_data); return; } fftease-2.5.2.git20121005/disarray~-help.pd0000644000076500007650000000357512067450034016512 0ustar hanshans#N canvas 863 421 559 421 10; #X obj 174 83 phasor~ 300; #N canvas 0 22 478 328 disarray_block 0; #X obj 107 116 disarray~ 3000 0 4 1; #X obj 107 59 inlet~; #X obj 186 65 inlet; #X obj 107 186 outlet~; #X obj 295 170 print; #X obj 188 206 block~ 256; #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 restore 174 133 pd disarray_block; #X obj 174 179 *~ 0.2; #X obj 174 216 dac~; #N canvas 673 80 659 338 messages 0; #X obj 172 305 outlet; #X obj 136 33 bng 15 250 50 0 empty empty empty 0 -6 0 8 -262144 -1 -1; #X floatatom 304 138 5 0 0 0 - - -; #X msg 304 163 topfreq \$1; #X msg 184 130 switch_count \$1; #X floatatom 184 104 5 0 0 0 - - -; #X msg 415 201 showstate; #X obj 421 277 fftease-system; #X msg 184 81 40; #X obj 184 54 loadbang; #X msg 304 112 4000; #X obj 304 88 loadbang; #X text 344 137 top frequency to scramble; #X text 222 73 number of bins to scramble; #X text 418 182 report current scramble; #X text 160 30 get new distribution; #N canvas 887 617 454 304 data 0; #X obj 8 226 outlet; #X msg 8 104 35 89 192 56 132 187 141 82 51 87 156 43 103 37 80 122 107 1 109 209 81; #X text 11 80 load your own data as a list; #X text 62 139 use the data reported from "showstate" as a start; #X connect 1 0 0 0; #X restore 405 245 pd data; #X connect 1 0 0 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 0 0; #X connect 7 0 0 0; #X connect 8 0 5 0; #X connect 9 0 8 0; #X connect 10 0 2 0; #X connect 11 0 10 0; #X connect 16 0 0 0; #X restore 288 90 pd messages; #X msg 26 166 \; pd dsp \$1; #X obj 26 143 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X text 286 75 open for controls:; #X text 36 283 disarray~ reorders the weights of spectral components below a specified top frequency.; #X connect 0 0 1 0; #X connect 1 0 2 0; #X connect 2 0 3 0; #X connect 2 0 3 1; #X connect 4 0 1 1; #X connect 6 0 5 0; fftease-2.5.2.git20121005/disarray~.c0000644000076500007650000003160212067450034015373 0ustar hanshans#include "MSPd.h" #include "fftease.h" #define MEMPAD (1024) #if MSP void *disarray_class; #endif #if PD static t_class *disarray_class; #endif #define OBJECT_NAME "disarray~" typedef struct _disarray { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // int *shuffle_in; int *shuffle_out; int shuffle_count; int max_bin; // float mult; float *trigland; int *bitshuffle; // float top_frequency; int overlap; int winfac; float c_fundamental; // void *list_outlet; t_atom *list_data; short mute; short bypass; short lock; } t_disarray; void *disarray_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *disarray_perform(t_int *w); void disarray_dsp(t_disarray *x, t_signal **sp, short *count); void disarray_assist(t_disarray *x, void *b, long m, long a, char *s); void switch_count (t_disarray *x, t_floatarg i); void iswitch_count (t_disarray *x, t_int i); void disarray_topfreq (t_disarray *x, t_floatarg freq); void reset_shuffle( t_disarray *x ); void disarray_showstate( t_disarray *x ); void disarray_list (t_disarray *x, t_symbol *msg, short argc, t_atom *argv); void disarray_setstate (t_disarray *x, t_symbol *msg, short argc, t_atom *argv); int rand_index( int max); void disarray_mute(t_disarray *x, t_floatarg toggle); void disarray_bypass(t_disarray *x, t_floatarg toggle); void disarray_tilde_setup(void); void disarray_free(t_disarray *x); void disarray_overlap(t_disarray *x, t_floatarg o); void disarray_winfac(t_disarray *x, t_floatarg o); void disarray_fftinfo(t_disarray *x); void disarray_init(t_disarray *x, short initialized); #if MSP void main(void) { setup((t_messlist **)&disarray_class, (method)disarray_new, (method)disarray_free, (short)sizeof(t_disarray), 0, A_GIMME, 0); addmess((method)disarray_dsp, "dsp", A_CANT, 0); addint((method)iswitch_count); addbang((method)reset_shuffle); addmess((method)disarray_showstate,"showstate",0); addmess ((method)disarray_list, "list", A_GIMME, 0); addmess ((method)disarray_setstate, "setstate", A_GIMME, 0); addmess((method)disarray_assist,"assist",A_CANT,0); addmess ((method)disarray_mute, "mute", A_FLOAT, 0); addmess ((method)disarray_topfreq, "topfreq", A_FLOAT, 0); addmess ((method)disarray_bypass, "bypass", A_LONG, 0); addmess((method)disarray_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)disarray_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)switch_count, "switch_count", A_DEFFLOAT, 0); addmess((method)disarray_fftinfo, "fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void disarray_tilde_setup(void) { disarray_class = class_new(gensym("disarray~"), (t_newmethod)disarray_new, (t_method)disarray_free ,sizeof(t_disarray), 0,A_GIMME,0); CLASS_MAINSIGNALIN(disarray_class, t_disarray, x_f); class_addmethod(disarray_class, (t_method)disarray_dsp, gensym("dsp"), 0); class_addmethod(disarray_class, (t_method)disarray_showstate, gensym("showstate"), 0); class_addmethod(disarray_class, (t_method)disarray_list, gensym("list"), A_GIMME, 0); class_addmethod(disarray_class, (t_method)disarray_mute, gensym("mute"), A_FLOAT, 0); class_addmethod(disarray_class, (t_method)disarray_topfreq, gensym("topfreq"), A_FLOAT, 0); class_addmethod(disarray_class, (t_method)switch_count, gensym("switch_count"), A_FLOAT, 0); class_addmethod(disarray_class, (t_method)reset_shuffle, gensym("bang"), 0); class_addmethod(disarray_class, (t_method)disarray_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(disarray_class, (t_method)disarray_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(disarray_class, (t_method)disarray_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void disarray_free(t_disarray *x) { #if MSP dsp_free((t_pxobject *) x); #endif free(x->Wanal); free(x->Wsyn); free(x->input); free(x->Hwin); free(x->buffer); free(x->channel); free(x->output); free(x->bitshuffle); free(x->trigland); free(x->list_data) ; } void disarray_overlap(t_disarray *x, t_floatarg o) { if(!fftease_power_of_two(o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; disarray_init(x,1); } void disarray_winfac(t_disarray *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; disarray_init(x,2); /* calling lighter reinit routine */ } void disarray_fftinfo( t_disarray *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void disarray_topfreq (t_disarray *x, t_floatarg freq) { float funda = (float) x->R / (2. * (float) x->N) ; float curfreq; if( freq < funda || freq > 20000) { freq = 1000.0 ; } x->max_bin = 1; curfreq = 0; while( curfreq < freq ) { ++(x->max_bin); curfreq += funda ; } } void disarray_assist (t_disarray *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input "); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"(signal) Output "); break; case 1: sprintf(dst,"(list) Current State "); break; } } } void *disarray_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_disarray *x = (t_disarray *)newobject(disarray_class); x->list_outlet = listout((t_pxobject *)x); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_disarray *x = (t_disarray *)pd_new(disarray_class); outlet_new(&x->x_obj, gensym("signal")); x->list_outlet = outlet_new(&x->x_obj,gensym("list")); #endif // INITIALIZATIONS srand( time( 0 ) ); x->D = sys_getblksize(); x->R = sys_getsr(); x->top_frequency = atom_getfloatarg(0,argc,argv); x->overlap = atom_getintarg(1,argc,argv); x->winfac = atom_getintarg(2,argc,argv); if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; disarray_init(x,0); return (x); } void disarray_init(t_disarray *x, short initialized) { int i; float curfreq; if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->c_fundamental = (float) x->R/(float)( (x->N2)<<1 ); x->mult = 1. / (float) x->N; x->lock = 1; if(initialized == 0){ x->Wanal = (float *) calloc( (MAX_Nw) , sizeof(float)); x->Wsyn = (float *) calloc( (MAX_Nw), sizeof(float)); x->input = (float *) calloc( (MAX_Nw), sizeof(float)); x->Hwin = (float *) calloc( (MAX_Nw), sizeof(float)); x->output = (float *) calloc( (MAX_Nw) , sizeof(float)); x->buffer = (float *) calloc( (MAX_N), sizeof(float)); x->channel = (float *) calloc( ((MAX_N+2)) , sizeof(float)); x->bitshuffle = (int *) calloc( ((MAX_N * 2)) , sizeof(int)); x->trigland = (float *) calloc( ((MAX_N * 2)) , sizeof(float)); x->shuffle_in = (int *) calloc( (MAX_N2), sizeof(int) ) ; x->shuffle_out = (int *) calloc( (MAX_N2), sizeof(int) ) ; x->list_data = (t_atom *) calloc( ((MAX_N+2)) , sizeof(t_atom) ) ; x->mute = 0; x->bypass = 0; x->shuffle_count = 0; } else { memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->channel,0,(x->N+2) * sizeof(float)); } init_rdft( x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); if(initialized != 2){ if( x->top_frequency < x->c_fundamental || x->top_frequency > 20000) { x->top_frequency = 1000.0 ; } x->max_bin = 1; curfreq = 0; while( curfreq < x->top_frequency ) { ++(x->max_bin); curfreq += x->c_fundamental ; } reset_shuffle(x); // set shuffle lookup x->shuffle_count = 0; } x->lock = 0; } void disarray_mute(t_disarray *x, t_floatarg toggle) { x->mute = (short)toggle; // post("muted: %d", x->mute); } void disarray_bypass(t_disarray *x, t_floatarg toggle) { x->bypass = (short)toggle; } t_int *disarray_perform(t_int *w) { t_disarray *x = (t_disarray *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); int n = w[4]; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *Hwin = x->Hwin; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; int i,j; int inCount = x->inCount; int D = x->D; float tmp; int shuffle_count = x->shuffle_count; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; int *shuffle_in = x->shuffle_in; int *shuffle_out = x->shuffle_out; if( x->mute || x->lock ){ while( n-- ){ *out++ = 0.0; } return (w+5); } if( x->bypass ){ while( n-- ){ *out++ = *in++ * 0.5; // gain compensation } return (w+5); } inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold(input, Wanal, Nw, buffer, N, inCount); rdft(N, 1, buffer, bitshuffle, trigland); leanconvert(buffer, channel, N2); for( i = 0; i < shuffle_count ; i++){ tmp = channel[ shuffle_in[ i ] * 2 ]; channel[ shuffle_in[ i ] * 2] = channel[ shuffle_out[ i ] * 2]; channel[ shuffle_out[ i ] * 2] = tmp; } leanunconvert( channel, buffer, N2 ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+5); } void iswitch_count(t_disarray *x, t_int i) { switch_count(x,(t_floatarg)i); } void switch_count (t_disarray *x, t_floatarg i) { if( i < 0 ){ i = 0; } if( i > x->N2 ) { i = x->N2; } x->shuffle_count = i; } void reset_shuffle (t_disarray *x) { int i; int temp, p1, p2; int max; //post("max bin %d",x->max_bin); max = x->max_bin; for( i = 0; i < x->N2; i++ ) { x->shuffle_out[i] = x->shuffle_in[i] = i ; } for( i = 0; i < 10000; i++ ) { p1 = x->shuffle_out[ rand_index( max ) ]; p2 = x->shuffle_out[ rand_index( max ) ]; temp = x->shuffle_out[ p1 ]; x->shuffle_out[ p1 ] = x->shuffle_out[ p2 ]; x->shuffle_out[ p2 ] = temp; } } int rand_index( int max) { return ( rand() % max ); } void disarray_dsp(t_disarray *x, t_signal **sp, short *count) { if(x->D != sp[0]->s_n ||x->D != sp[0]->s_n ) { x->R = sp[0]->s_sr; x->D = sp[0]->s_n; disarray_init(x,1); } dsp_add(disarray_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } // ENTER STORED SHUFFLE void disarray_list (t_disarray *x, t_symbol *msg, short argc, t_atom *argv) { short i; int ival; x->shuffle_count = argc; for (i=0; i < argc; i++) { ival = (int)atom_getfloatarg(i,argc,argv); if ( ival < x->N2 ) { x->shuffle_out[ i ] = ival; } else { post ("%d out of range",ival); } } return; } void disarray_setstate (t_disarray *x, t_symbol *msg, short argc, t_atom *argv) { short i; int ival; x->shuffle_count = argc; for (i=0; i < argc; i++) { ival = atom_getfloatarg(i,argc,argv); if ( ival < x->N2 && ival >= 0) { x->shuffle_out[ i ] = ival; } else { error("%s: %d is out of range",OBJECT_NAME, ival); } } return; } // REPORT CURRENT SHUFFLE STATUS void disarray_showstate (t_disarray *x ) { t_atom *list_data = x->list_data; short i; #if MSP for( i = 0; i < x->shuffle_count; i++ ) { SETLONG(list_data+i,x->shuffle_out[i]); } #endif #if PD for( i = 0; i < x->shuffle_count; i++ ) { SETFLOAT(list_data+i,(float)x->shuffle_out[i]); } #endif outlet_list(x->list_outlet,0,x->shuffle_count,list_data); return; } fftease-2.5.2.git20121005/drown~-help.pd0000644000076500007650000000336612067450034016023 0ustar hanshans#N canvas 1012 277 466 316 10; #N canvas 0 22 470 320 drown-block 0; #X obj 178 165 drown~ 0.001 0.1 4 1; #X obj 178 195 outlet~; #X obj 178 124 inlet~; #X obj 245 123 inlet; #X obj 313 125 inlet; #X obj 371 129 inlet; #X obj 178 232 block~ 256; #X connect 0 0 1 0; #X connect 2 0 0 0; #X connect 3 0 0 1; #X connect 4 0 0 2; #X connect 5 0 0 0; #X restore 18 93 pd drown-block; #X obj 18 140 dac~; #X msg 24 256 \; pd dsp \$1; #X obj 24 233 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X floatatom 49 49 5 0 0 0 - threshold -; #X floatatom 80 65 5 0 0 0 - noise-gain -; #N canvas 730 185 462 312 sound-source 0; #X obj 127 102 osc~ 350; #X obj 127 194 outlet~; #X obj 249 107 noise~; #X obj 127 155 *~ 0.1; #X obj 249 143 *~ 0.03; #X text 58 103 signal ->; #X text 298 110 <- add noise; #X connect 0 0 3 0; #X connect 2 0 4 0; #X connect 3 0 1 0; #X connect 4 0 1 0; #X restore 18 7 pd sound-source; #N canvas 928 509 470 320 messages 0; #X obj 231 210 outlet; #N canvas 0 22 458 308 init 0; #X obj 333 21 loadbang; #X obj 333 71 unpack f f; #X obj 333 103 s drown-s1; #X obj 362 129 s drown-s2; #X msg 333 48 0.01 1; #X connect 0 0 4 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 4 0 1 0; #X restore 89 104 pd init; #X obj 231 180 fftease-system; #X connect 2 0 0 0; #X restore 163 77 pd messages; #X obj 26 173 hsl 128 15 0 0.02 0 0 threshold drown-s1 threshold -2 -6 0 8 -189148 -1 -1 6800 1; #X obj 26 211 hsl 128 15 0 1 0 0 noise-gain drown-s2 noise-gain -2 -6 0 8 -189148 -1 -1 0 1; #X text 160 210 <- reduce noise here; #X text 160 172 <- threshold to block noise; #X text 103 265 threshold-based noise reduction; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 3 0 2 0; #X connect 4 0 0 1; #X connect 5 0 0 2; #X connect 6 0 0 0; #X connect 7 0 0 3; fftease-2.5.2.git20121005/drown~.c0000644000076500007650000002426412067450034014714 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *drown_class; #endif #if PD static t_class *drown_class; #endif #define OBJECT_NAME "drown~" typedef struct _drown { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float drownmult; // float threshgen; short mute; float threshold; // faster FFT float mult; float *trigland; int *bitshuffle; short connected[8]; int overlap;//overlap factor int winfac;//window factor int vs;//vector size short peakflag;// means threshold is relative to peak amp // } t_drown; void *drown_new(t_symbol *s, int argc, t_atom *argv); void drown_mute(t_drown *x, t_floatarg toggle); void drown_rel2peak(t_drown *x, t_floatarg toggle); //t_int *offset_perform(t_int *w); t_int *drown_perform(t_int *w); void drown_dsp(t_drown *x, t_signal **sp, short *count); void drown_assist(t_drown *x, void *b, long m, long a, char *s); void nudist( float *S, float *C, float threshold, float fmult, int N2 ); void drown_float(t_drown *x, double f); void drown_overlap(t_drown *x, t_floatarg o); void drown_free(t_drown *x); void drown_init(t_drown *x, short initialized); void drown_overlap(t_drown *x, t_floatarg f); void drown_winfac(t_drown *x, t_floatarg f); void drown_fftinfo(t_drown *x); #if MSP void main(void) { setup((t_messlist **)&drown_class, (method)drown_new, (method)drown_free, (short)sizeof(t_drown), 0, A_GIMME, 0); addmess((method)drown_dsp, "dsp", A_CANT, 0); addmess((method)drown_assist,"assist",A_CANT,0); addmess((method)drown_mute,"mute",A_FLOAT,0); addmess((method)drown_rel2peak,"rel2peak",A_FLOAT,0); addmess((method)drown_overlap,"overlap",A_FLOAT,0); addmess((method)drown_winfac,"winfac",A_FLOAT,0); addmess((method)drown_fftinfo,"fftinfo",0); addfloat((method)drown_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if MSP void drown_float(t_drown *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; // post("drown: incoming float: %f",f); // post("inlet %d",inlet); if (inlet == 1) { x->threshold = f; } if (inlet == 2) { x->drownmult = f; } } #endif #if PD void drown_tilde_setup(void) { drown_class = class_new(gensym("drown~"), (t_newmethod)drown_new, (t_method)drown_free ,sizeof(t_drown), 0,A_GIMME,0); CLASS_MAINSIGNALIN(drown_class, t_drown, x_f); class_addmethod(drown_class, (t_method)drown_dsp, gensym("dsp"), 0); class_addmethod(drown_class, (t_method)drown_assist, gensym("assist"), 0); class_addmethod(drown_class, (t_method)drown_mute, gensym("mute"), A_FLOAT,0); class_addmethod(drown_class, (t_method)drown_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(drown_class, (t_method)drown_rel2peak, gensym("rel2peak"), A_FLOAT,0); class_addmethod(drown_class, (t_method)drown_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(drown_class, (t_method)drown_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(drown_class, (t_method)drown_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void drown_overlap(t_drown *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; drown_init(x,1); } void drown_winfac(t_drown *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; drown_init(x,2); } void drown_fftinfo(t_drown *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void drown_rel2peak(t_drown *x, t_floatarg toggle) { x->peakflag = (short)toggle; } void drown_mute(t_drown *x, t_floatarg toggle) { x->mute = (short)toggle; } void drown_assist (t_drown *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Threshold Generator"); break; case 2: sprintf(dst,"(signal/float) Multiplier for Weak Bins"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void *drown_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_drown *x = (t_drown *)newobject(drown_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_drown *x = (t_drown *)pd_new(drown_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->threshold = atom_getfloatarg(0,argc,argv); x->drownmult = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(x->threshold <= 0) x->threshold = .0001; if(x->drownmult <= 0) x->drownmult = 0.1; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->vs = sys_getblksize(); x->R = sys_getsr(); drown_init(x,0); return (x); } void drown_init(t_drown *x, short initialized) { int i; int mem; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->peakflag = 0; mem = (MAX_Nw) * sizeof(float); x->input = (float *) getbytes(mem); x->output = (float *) getbytes(mem); x->Wanal = (float *) getbytes(mem); x->Wsyn = (float *) getbytes(mem); x->Hwin = (float *) getbytes(mem); mem = (MAX_N) * sizeof(float); x->buffer = (float *) getbytes(mem); mem = (MAX_N+2) * sizeof(float); x->channel = (float *) getbytes(mem); mem = (MAX_N) * sizeof(int); x->bitshuffle = (int *) getbytes(mem); mem = (MAX_N) * sizeof(float); x->trigland = (float *) getbytes(mem); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); init_rdft( x->N, x->bitshuffle, x->trigland); } void drown_free(t_drown *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); } t_int *drown_perform(t_int *w) { int i,j; float frame_peak = 0.0; float local_thresh; t_drown *x = (t_drown *) (w[1]); t_float *in = (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]); t_int n = w[6]; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; int inCount = x->inCount ; int on = inCount; float threshold = x->threshold; float drownmult = x->drownmult; short *connected = x->connected; // get multiplier from sig inlet /* dereference struncture */ if( x->mute ){ while( n-- ){ *out++ = 0.0; } return (w+7); } if( connected[1] ) threshold = *in2++ ; if( connected[2] ) drownmult = *in3++ ; inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft(N, 1, buffer, bitshuffle, trigland); if( x->peakflag ){ leanconvert( buffer, channel, N2); for(i = 0; i inCount = inCount % Nw; return (w+7); } void nudist( float *S, float *C, float threshold, float fmult, int N2 ) { int real, imag, amp, phase; float a, b; int i; float maxamp = 1.; for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; a = ( i == N2 ? S[1] : S[real] ); b = ( i == 0 || i == N2 ? 0. : S[imag] ); C[amp] = hypot( a, b ); if ( (C[amp]) < threshold ){ C[amp] *= fmult; } C[phase] = -atan2( b, a ); } for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; S[real] = *(C+amp) * cos( *(C+phase) ); if ( i != N2 ) S[imag] = -*(C+amp) * sin( *(C+phase) ); } } void drown_dsp(t_drown *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 4; i++ ){ x->connected[i] = count[i]; } #endif #if PD for( i = 0; i < 4; i++ ){ x->connected[i] = 1; } #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; drown_init(x,1); } dsp_add(drown_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/ether~-help.pd0000644000076500007650000000767312067450034016006 0ustar hanshans#N canvas 281 24 660 446 10; #X obj 167 237 *~ 1; #X obj 167 289 dac~; #X floatatom 190 218 5 0 0 0 - centerring-gain -; #X msg 333 284 \; pd dsp \$1; #X obj 333 267 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 17 207 hsl 128 15 0 4 0 0 centerring-gain empty output_gain -2 -6 0 8 -79789 -1 -1 1900 1; #N canvas 0 22 511 346 messages 0; #X obj 132 268 outlet; #X msg 34 232 fftinfo; #X msg 132 74 mute \$1; #X obj 132 41 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X msg 25 101 overlap \$1; #X msg 25 54 2; #X msg 55 71 4; #X text 208 216 turn on invert; #X text 221 177 is turned on; #X obj 187 217 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X msg 187 239 invert \$1; #X text 221 163 pad affects the gain only when "invert"; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 0 0; #X connect 5 0 4 0; #X connect 6 0 4 0; #X connect 9 0 10 0; #X connect 10 0 0 0; #X restore 448 167 pd messages; #X obj 18 241 hsl 128 15 0 256 0 0 eth-composite-index empty composite_index -2 -6 0 8 -88868 -1 -1 0 1; #N canvas 990 218 500 389 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #X msg 31 177 read -resize \$1 ether-sound1; #X obj 227 268 tabplay~ ether-sound1; #N canvas 0 0 450 300 graph1 0; #X array ether-sound1 449212 float 2; #X coords 0 1 449211 -1 200 140 1; #X restore 244 30 graph; #X connect 1 0 11 0; #X connect 2 0 1 0; #X connect 4 0 12 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 11 0 0 0; #X connect 12 0 3 0; #X connect 12 1 5 0; #X restore 167 97 pd playsound1; #N canvas 936 488 508 397 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #X msg 31 177 read -resize \$1 ether-sound2; #N canvas 0 0 450 300 graph2 0; #X array ether-sound2 1.764e+06 float 2; #X coords 0 1 1.764e+06 -1 200 140 1; #X restore 236 17 graph; #X obj 227 268 tabplay~ ether-sound2; #X connect 1 0 11 0; #X connect 2 0 1 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 11 0 0 0; #X connect 13 0 3 0; #X connect 13 1 5 0; #X restore 198 116 pd playsound2; #X floatatom 229 159 5 0 0 0 - eth-composite-index -; #X text 286 101 <- load and loop two soundfiles to hear effect; #X obj 14 107 loadbang; #X text 31 316; #X text 23 318 ether~ selects portions of two input signals and creates a composite output spectrum based upon the amplitude of the inputs. The loudest band of the two inputs will be selected. Sending the inverse message will reverse this behavior selecting the weakest. The composite index is a scalar for the selection of the second input. Useful values will vary according to the amplitude characteristics of the input signals. Try values greater than 0 and less than 100 But higher values may be effective depending upon the input signals.; #N canvas 376 316 474 324 ether-block 0; #X obj 233 219 block~ 256; #X obj 163 185 outlet~; #X obj 163 38 inlet~; #X obj 269 107 inlet; #X obj 201 81 inlet; #X obj 181 60 inlet~; #X obj 163 128 ether~; #X connect 2 0 6 0; #X connect 3 0 6 0; #X connect 4 0 6 2; #X connect 5 0 6 1; #X connect 6 0 1 0; #X restore 167 183 pd ether-block; #X text 270 159 composite index; #X msg 14 123 0.1 1; #X obj 14 139 unpack f f; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 2 0 0 1; #X connect 4 0 3 0; #X connect 6 0 15 3; #X connect 8 0 15 0; #X connect 9 0 15 1; #X connect 10 0 15 2; #X connect 12 0 17 0; #X connect 15 0 0 0; #X connect 17 0 18 0; #X connect 18 0 5 0; #X connect 18 1 7 0; fftease-2.5.2.git20121005/ether~.c0000644000076500007650000003030612067450034014664 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *ether_class; #endif #if PD static t_class *ether_class; #endif #define OBJECT_NAME "ether~" /* Added a new inlet for the composite index */ typedef struct _ether { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int invert; int *bitshuffle; float threshMult; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_ether; void *ether_new(t_symbol *s, int argc, t_atom *argv); t_int *ether_perform(t_int *w); void ether_dsp(t_ether *x, t_signal **sp, short *count); void ether_assist(t_ether *x, void *b, long m, long a, char *s); void ether_dest(t_ether *x, double f); void ether_invert(t_ether *x, t_floatarg toggle); void ether_init(t_ether *x, short initialized); void ether_free(t_ether *x); void ether_mute(t_ether *x, t_floatarg toggle); void ether_fftinfo(t_ether *x); void ether_winfac(t_ether *x, t_floatarg f); void ether_overlap(t_ether *x, t_floatarg o); void ether_tilde_setup(void); #if MSP void main(void) { setup((t_messlist **)ðer_class, (method) ether_new, (method)ether_free, (short) sizeof(t_ether), 0, A_GIMME, 0); addmess((method)ether_dsp, "dsp", A_CANT, 0); addmess((method)ether_assist,"assist",A_CANT,0); addfloat((method)ether_dest); addmess((method)ether_invert,"invert", A_FLOAT, 0); addmess((method)ether_mute,"mute", A_FLOAT, 0); addmess((method)ether_overlap,"overlap", A_FLOAT, 0); addmess((method)ether_winfac,"winfac", A_FLOAT, 0); addmess((method)ether_fftinfo,"fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } void ether_dest(t_ether *x, double f) { x->threshMult = (float) f; } #endif #if PD void ether_tilde_setup(void) { ether_class = class_new(gensym("ether~"), (t_newmethod)ether_new, (t_method)ether_free ,sizeof(t_ether), 0,A_GIMME,0); CLASS_MAINSIGNALIN(ether_class, t_ether, x_f); class_addmethod(ether_class, (t_method)ether_dsp, gensym("dsp"), 0); class_addmethod(ether_class, (t_method)ether_assist, gensym("assist"), 0); class_addmethod(ether_class, (t_method)ether_invert, gensym("invert"), A_FLOAT,0); class_addmethod(ether_class, (t_method)ether_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(ether_class, (t_method)ether_mute, gensym("mute"), A_FLOAT,0); class_addmethod(ether_class, (t_method)ether_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(ether_class, (t_method)ether_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif /* diagnostic messages for Max */ void ether_assist (t_ether *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input One");break; case 1: sprintf(dst,"(signal) Input Two"); break; case 2: sprintf(dst,"(signal) Composite Index"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void ether_free(t_ether *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->inputTwo,0); freebytes(x->bufferOne,0); freebytes(x->bufferTwo,0); freebytes(x->channelOne,0); freebytes(x->channelTwo,0); freebytes(x->output,0); } void ether_overlap(t_ether *x, t_floatarg df) { int o = (int)df; if(!fftease_power_of_two(o)){ error("%d is not a power of two",o); return; } x->overlap = o; ether_init(x,1); } void ether_winfac(t_ether *x, t_floatarg f) { int wf = (int)f; if(!fftease_power_of_two(wf)){ error("%f is not a power of two",f); return; } x->winfac = wf; ether_init(x,1); } void ether_fftinfo( t_ether *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void *ether_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_ether *x = (t_ether *) newobject(ether_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_ether *x = (t_ether *)pd_new(ether_class); /* add two additional signal inlets */ inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: overlap winfac */ x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } x->vs = sys_getblksize(); x->R = sys_getsr(); ether_init(x,0); return (x); } void ether_init(t_ether *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->invert = 0; x->threshMult = 0.; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->inputOne = (float *) getbytes(MAX_Nw * sizeof(float)); x->inputTwo = (float *) getbytes(MAX_Nw * sizeof(float)); x->bufferOne = (float *) getbytes(MAX_N * sizeof(float)); x->bufferTwo = (float *) getbytes(MAX_N * sizeof(float)); x->channelOne = (float *) getbytes(MAX_N+2 * sizeof(float)); x->channelTwo = (float *) getbytes(MAX_N+2 * sizeof(float)); x->output = (float *) getbytes(MAX_Nw * sizeof(float)); x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int)); x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float)); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1); } t_int *ether_perform(t_int *w) { int i,j, inCount, R, N, N2, D, Nw, invert = 1, even, odd, *bitshuffle; float maxamp, threshMult = 1., mult, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; /* get our inlets and outlets */ t_ether *x = (t_ether *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *vec_threshMult = (t_float *)(w[4]); t_float *out = (t_float *)(w[5]); t_int n = w[6]; short *connected = x->connected; /* dereference structure */ inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; invert = x->invert; if(connected[2]){ threshMult = *vec_threshMult; } else if ( x->threshMult != 0. ){ threshMult = x->threshMult; } else { threshMult = 1.0; } if(x->mute){ while(n--) *out++ = 0.0; return w+7; } /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* use slow fft */ /* use redundant coding for speed, even though moving the invert variable comparison outside of the for loop will give us only a minimal performance increase (hypot and atan2 are the most intensive portions of this code). consider adding a table lookup for atan2 instead. */ if (invert) { /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); /* use simple threshold for inverse compositing */ if ( *(channelOne+even) > *(channelTwo+even) * threshMult ) *(channelOne+even) = *(channelTwo+even); if ( *(channelOne+odd) == 0. ) *(channelOne+odd) = *(channelTwo+odd); } } else { /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); /* use simple threshold for compositing */ if ( *(channelOne+even) < *(channelTwo+even) * threshMult ) *(channelOne+even) = *(channelTwo+even); if ( *(channelOne+odd) == 0. ) *(channelOne+odd) = *(channelTwo+odd); } } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void ether_mute(t_ether *x, t_floatarg toggle) { x->mute = (short)toggle; } void ether_invert(t_ether *x, t_floatarg toggle) { x->invert = (int)toggle; } void ether_dsp(t_ether *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 3; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 3; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; ether_init(x,1); } dsp_add(ether_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/examples/0000755000076500007650000000000012067452122015027 5ustar hanshansfftease-2.5.2.git20121005/examples/13et.scale0000644000076500007650000000223612067452034016621 0ustar hanshans27.5000 29.0061 30.5946 32.2702 34.0375 35.9016 37.8678 39.9416 42.1291 44.4363 46.8699 49.4368 52.1443 55.0000 58.0121 61.1892 64.5403 68.0749 71.8031 75.7355 79.8833 84.2581 88.8726 93.7398 98.8736 104.2885 110.0000 116.0243 122.3785 129.0807 136.1499 143.6063 151.4710 159.7665 168.5163 177.7453 187.4797 197.7472 208.5771 220.0000 232.0485 244.7569 258.1613 272.2998 287.2126 302.9421 319.5330 337.0326 355.4906 374.9594 395.4944 417.1541 440.0000 464.0971 489.5138 516.3226 544.5996 574.4251 605.8842 639.0661 674.0652 710.9811 749.9187 790.9889 834.3082 880.0000 928.1941 979.0277 1032.6452 1089.1991 1148.8503 1211.7683 1278.1321 1348.1304 1421.9622 1499.8375 1581.9777 1668.6164 1760.0000 1856.3883 1958.0554 2065.2904 2178.3983 2297.7006 2423.5366 2556.2642 2696.2608 2843.9244 2999.6750 3163.9554 3337.2329 3520.0000 3712.7766 3916.1108 4130.5808 4356.7965 4595.4012 4847.0733 5112.5285 5392.5216 5687.8488 5999.3500 6327.9109 6674.4657 7040.0000 7425.5532 7832.2216 8261.1616 8713.5930 9190.8024 9694.1465 10225.0569 10785.0432 11375.6977 11998.7000 12655.8217 13348.9314 14080.0000 14851.1064 15664.4432 16522.3233 17427.1861 18381.6047 19388.2931 20450.1138 21570.0863 fftease-2.5.2.git20121005/examples/24et.scale0000644000076500007650000000420112067452034016615 0ustar hanshans27.5000 28.3058 29.1352 29.9890 30.8677 31.7722 32.7032 33.6615 34.6478 35.6631 36.7081 37.7837 38.8909 40.0305 41.2034 42.4108 43.6535 44.9327 46.2493 47.6045 48.9994 50.4352 51.9131 53.4343 55.0000 56.6116 58.2705 59.9779 61.7354 63.5444 65.4064 67.3229 69.2957 71.3262 73.4162 75.5675 77.7817 80.0609 82.4069 84.8216 87.3071 89.8653 92.4986 95.2090 97.9989 100.8704 103.8262 106.8685 110.0000 113.2232 116.5409 119.9559 123.4708 127.0888 130.8128 134.6459 138.5913 142.6524 146.8324 151.1349 155.5635 160.1219 164.8138 169.6432 174.6141 179.7307 184.9972 190.4180 195.9977 201.7409 207.6523 213.7370 220.0000 226.4465 233.0819 239.9117 246.9417 254.1776 261.6256 269.2918 277.1826 285.3047 293.6648 302.2698 311.1270 320.2437 329.6276 339.2864 349.2282 359.4614 369.9944 380.8361 391.9954 403.4818 415.3047 427.4741 440.0000 452.8930 466.1638 479.8234 493.8833 508.3552 523.2511 538.5836 554.3653 570.6094 587.3295 604.5396 622.2540 640.4874 659.2551 678.5728 698.4565 718.9228 739.9888 761.6722 783.9909 806.9636 830.6094 854.9481 880.0000 905.7860 932.3275 959.6468 987.7666 1016.7104 1046.5023 1077.1671 1108.7305 1141.2188 1174.6591 1209.0792 1244.5079 1280.9748 1318.5102 1357.1455 1396.9129 1437.8456 1479.9777 1523.3443 1567.9817 1613.9271 1661.2188 1709.8962 1760.0000 1811.5719 1864.6550 1919.2936 1975.5332 2033.4207 2093.0045 2154.3342 2217.4610 2282.4376 2349.3181 2418.1584 2489.0159 2561.9496 2637.0205 2714.2911 2793.8259 2875.6912 2959.9554 3046.6887 3135.9635 3227.8542 3322.4376 3419.7924 3520.0000 3623.1439 3729.3101 3838.5872 3951.0664 4066.8415 4186.0090 4308.6685 4434.9221 4564.8752 4698.6363 4836.3168 4978.0317 5123.8992 5274.0409 5428.5821 5587.6517 5751.3824 5919.9108 6093.3774 6271.9270 6455.7085 6644.8752 6839.5849 7040.0000 7246.2877 7458.6202 7677.1744 7902.1328 8133.6830 8372.0181 8617.3369 8869.8442 9129.7505 9397.2726 9672.6337 9956.0635 10247.7984 10548.0818 10857.1642 11175.3034 11502.7648 11839.8215 12186.7548 12543.8540 12911.4169 13289.7503 13679.1697 14080.0000 14492.5755 14917.2404 15354.3489 15804.2656 16267.3660 16744.0362 17234.6739 17739.6884 18259.5009 18794.5451 19345.2674 19912.1270 20495.5968 21096.1636 21714.3284 fftease-2.5.2.git20121005/examples/4th.scale0000644000076500007650000000034112067452034016537 0ustar hanshans27.5000 36.6667 48.8889 65.1852 86.9136 115.8848 154.5130 206.0174 274.6898 366.2531 488.3375 651.1166 868.1555 1157.5407 1543.3876 2057.8501 2743.8002 3658.4002 4877.8670 6503.8226 8671.7635 11562.3514 15416.4685 20555.2913 fftease-2.5.2.git20121005/examples/Piano.aif0000644000076500007650000026521412067450034016570 0ustar hanshansFORMj„AIFFCOMMµ+@¬DSSNDj^ÿšÿÿ©ÿ´ÿ¾ÿŽÿÿ©ÿ€ÿŠÿÓÿ²ÿÿˆÿ‰ÿ¤ÿÃÿ“ÿ€ÿ‚ÿªÿ£ÿ²ÿÏÿ²ÿ³{³ÿE@Eéñ Ü ; € K G ½ I d  Ì y Ü z aÁ Ø Í  ¸ õ ‚ ý E …  a 7 § • ž Ï 0 —ÊzцG°@ 4 x è  ø d ˜ 'Ì Vvó ‡ Û … ýÇúvø÷Ÿ÷íùÆüBþßí¯Yÿßýäûzù÷öI÷ø¿úaûúþúYù´ù ÷½ö¦öªøùñûÂüÓýAþŽÔ²;þ³øZñ¢íìñƒúJ 1”0 [ ­ j³šaüeøõ±ô7ó@ñ[íJç>à±Û(×1ÔЎ̯È`Ä{Àî½X»S»£¾üÅ1ÍIÕNÜ“ã æÆèñêêÒëƒìÆðVõ’û<#Èae; G“·´ÓÏ „#p+>14‘4f1¦.i,¤,Ç.Û2€6§9Õ:˜7Ö2m+Û%S à #ª(ù.v2Ÿ3¦2.é*Æ'M%%Ô'±*Á-.V,ù)J$]W挣m!G!+“m7¾ øìíí UØ#Yd ÈOÿ7ù2ôÖòñ÷ò—ó5ñ¡í”èuä~âsââ¼äæ)é¦îUóföÇõrï ã\ÖÌMÉAÏGÛHé!ôâüKþ­ûíömïïênç>æ;æìé®îÂôîú÷ÿï¤/T/ý°û´ú/ù ÷Pô5ïÓêã–Ý0ÖàÑÌÈ8ÅÄBÃÈÂC¾é¸'® £V™á”“+–kœ¤¼®Ÿ¹bÛÌFѰÓgÓÒ(ÒÊÖ*Üdãõë½ñåõóöÒôþñòîìØïÀ÷žK OÉÇåªòf!Ú#Ó+’3Þ:Ñ?@>:7[6‡7¾:/<ƒ=û>l=Z9É45.v*Ë*w-;2V8¡=ÂA As=’6n-ó%éVóö=$B*Ø1R5H4ä/‹&äd…Ù³ ‘&**-,É-•+¶&ßþÜ Óy<ó  â ¿þínÜÃÏúÉ.ÊѺÜÅèSòkøåú‡ø&ñèèrÞ>ÕÙЎΚÏÛÔ¥Ü9åoíªñ¹ñdíyèeãÞ¦ÛâÛáÞñä¾ìEó4÷Òù}ù°úüÿÜ$ ât2Âøj 0*Sÿëýüúªù öðÞéÞ2ÐÆÁê²Ç¥;šÈ••¬š2¡˜§Ö««½«²­±½¸ŠÀvÊRÔ]ÝÅå¢ééIæ!â]ߣßáåžìÉõ§ýðu /S„Lþnȶ!þ%Ó)u,-./Ö2m7.L¢H0C>Ù=5>RAÒFºIÓI/Dq<¿4Æ-ê)„&a#ß#$P(š/‚7=Ž>:A0þ'M ô¦ «'/6p:~9’4…,Ú&W"Ï#C&¿+>/F1R0†*Þ dÊÞð™âàØóÓ›Ó†Ö~Üã èÐìÚí‡ê£ä-ÛöÔsÏÏÏÙÓÅÚŒá>å¡ç[æÐå:ã áCàá9ä;é;ï!ô¥÷…ø\÷Ä÷GøŸúû…üYý…PÂtÛnü·÷7ô)ô‹÷Cûþéyþ£ùÌñkæ ͔٘Ãt» ´®º©%¢òœA•ÆCŒ×Œúw–jžÐ¨€²Z»rÂÆ1ÇðÈYɫˡÎ,ÑÜÕ£ÙGÛqÜ?Üݰá*åéúîðò…õ÷úúûæú"÷%ô±õ>úÄv¹E \#k$™%‰$é$B#ù$6%Æ(å-õ5‚=éF0L6MOI¶B8g/W){(*".3”6—6]3.)<%‹$$Ù(E-°3¬8²:€8C3´.,(Ÿ$¯"}"A#Ô'µ.B6ƒ>AÆ?85—'ž– þõkð/îsïuñÓòûñåî÷ë(çŠåläìå%åTåärä$äÍæ_èoéíêéŠè—è‰éwëoîCðàòXò!ñ+ï÷ï‚ïñ ôwù‚ÿh‰$Ø­´þ¨ü·ütýiÿÙôÓNèZsþ:ùlô˜ïáë˜çÎâ÷ۨчÃíµ”©eŸøšá™¼š&›©žì£øª'²¹t¿AõÇÄÌ]ѦרÝ%àâà’ÝÅÙÌÖ¡ÖÌÛ-â;épï©ô'öUöæö¾õHócñdï·ïKð/ó@øá¤ %31Èž˜_¤Ð%W1=®HƒO/OKD±?:=s?]CLGOJPK«K‰J4G‚Bï=L85À5Ã9=?EÙKM>L¦H’@ç7T-Ø&Ù$é(j0z:äELNÛMÑJ+E·@8©/¶%Ýׯ Ød£þ€û_øxõVòËñ'ï·ïiïí™ë5çÈä;áÞ™Ý^Þ8à³ãzå‰åXâUÝ_Ø5ÔÐÓ¥Õ×ÊÚ¶ÞGâ/åŒèècæ‡ãàþàåãçþì5î÷îçìúê_èèlêÖíÈð3ñXñAðæðãïŽëRã¼ØßÌ^¿´´…«•¤Ržp™•~‘ÀH‚“š¥š±É¼¿ÅËÏ)Ò ÔhÕnÕ ÔHÔkÖvÛ3â,é¡ñ ø2ýèj¥ýÃ÷zððì‡ì½òúèÎ DÝa Á © o ÝÂo!ä+&4 ;*?’A @?ã?•?Ô@ßC€HM¶S£WU­OXEˆ;G3S/|0l5N<4CçIÀL5K¨H8B :ø3ä-K(Î&ø'ä+&0|6h;Æ@bDF4F D@À<7—3«/¤+A%B>5£ ýÐÂ7Ÿæÿˆü`ù/õÏó%òæôÉøaüQýù}ò}ê~ã”ßÐß›â(äôçdéhê5êÀê¾êNéÁéwéæêäìÀïðÀòBòìðøì/æžáÿàbâ¥çòíîòËõ\õâõ(ò¿ïXë~ç9áÂÚÌÒÅÉ‹¾ê²Ï¦š)͈%ƒÙ‚¼„Tˆ ®™P¤ø°4¸m¼(ºâ¶µ²“±Ùµ¶½#Ç+ÒÝIå¼êWê¸çÆâœÞ#ܻޢâÁèDî,óÀøjûFü˜üVúa÷ºö<öªùýn e´Z!ß$>#ø"»"†$‚(Ë/6s=ÅDHÂJ9HD>.7æ3>0".É/0ï4 8k=+AC¢Cf?¶8Ÿ/¹('"ü 3ötè +#ë(ú-’0Ð2À34±5-4v1O,%u:/2D ;Îýú™úûòýÇþèÿ_ÿ¹ÿŸÿýŽúìöîòEí¾êTé<ê)ëHëìëè÷æËåä¤åƒç£éûëïí‡í¡ìcéšåcá:Þ Ý%ÝÈÞÐÞäÞaÞîá#å@ë4ðcóÆõÛõýõOôàóOðpë§ãžØ°Éõ¸¦:–•‹ … …”‹’õšù¡Ñ¥~¥}¤+¢º¢ô¥7©s¯·K¿uÈqÑv׸Û+Û4؃ՑӑÓÿ×wÞæ6îZôãø2ø”ö/ò,îmëÌì/ð5÷cBû“e§2« #' .Ã7à@QFqI%G‚C>9¿6B4 3N3´69»>DCºH~KKK3IE»B*>Ë;¥8C3M-Ù(ç%_$”'h-š5©=‹CLFvF¶E‹D$BêBwB0A×AD@]?Ö>­;Ê7(0-(V!=R[–РKå_å¿&š‰x+K  {*uþŸüüý?ÿÙò¡X`{ŸÖýGù‚öóðmï*ïtï¶ïVî ëÁê-ë‘ðêùþ O§höDæIÔÁÄ‚¶­«u£Qž7œƒœkœM›„™•´’ûå«’¢–âó¦ö°Ä¹B¾üÁA¿×½†¼å¿#ÄFË\Ñú×ÌÜÔàÀãåRæ4æŠåÁä½ä»æïë×òøü7ÿ(WäPŸ ¾[´#í/'9¤AUFGHDüA==†;_;_B«HqM5PQAORKdF5?6’.u(@$€#|$;&X(ô+»./†0r0„0/Ù0w2#5ª9f;y:6V/s'j ‚„wº¾w h 9 Si â~¼Tÿ›þýü%úö¯òUíêê;èPè§ëåñ>öùÓúI÷½óºð™î×ïxñ¸ôcôíò×ï€é âÙßÒbͶÍcÑöÛæâò„üÞt  ãØÿ„óîåÝ×ÊÉÂ¼Š¸Œ³û­£2—Ìq…ÿ‚X‚X‚X„qˆ¦ç’Þ–ú™d𙇙™ûœè¡Í¨s¯]¶ »¶¿CÁ„Ã,ÅcÇýÊ·ÌãÎbÏöÒº×bÝ|ãÛèé8è§çæ8æ»è²ì¡òKøÅÿÑKí"%z.5:><Ú=:;"7C2ë/Ñ. 0P4^:'@ EëK¬PˆUW UrP”InBð>M;ø;“;«:Ø9X6p2¥/3,Û-p0L5f;?bB˜DCëB£@þ?Ï? >:<­9¶5/…*%í#u"" Äwo[TbÙÂk’5º iäàôtBQ3²Ö½Ü÷ -à ²º  #õ5éÜâ Þìá²é€ôÿþ ;øª2­Š ÛÖýíø"ñìé„ÞQЀÂIµ«½¥9 áž­˜œÍËžšŸÍ  ž©œššÙž¤ç¬Ú´¥ºº¾©À|ÀËÀgÀÀ…ÂþÈ\αÕÛ ÞÈàáâ}ãôå;åÛåãàÇßÓáÈåMêyñîú¿Æ²=$›-€4;7Ø73†.H)‘'Š)-µ4è<ÁCçIÛLÜNN$M9MXN¢P;QnPöMðHÕBó=‘9@63é1Û0w/.ü14æ9š=—@j@ü@W?D>:=Ä=ÐAÈCcDyDŒDBº?Ù;—5a/ *è(ü)ù,°/¿2R3z3q2=2 4¤8:>5a/Ú*Ÿ%þ#"©$g&ý)9)&|!ÍŠ¨Ï²ÕèÔn :7öDïšìüïéöÆÿŠ SÔ/Úç§ 2ýô÷”ò?îOëêsëìhîoðÈófö¤ûQ ¹ïÙ bfξþ4õòí¤ä˜ÛÚÔ>ÌÅ/¾·É±gªß¤ÍŸìœIš„™¸™ƒ™¼šy›Óž&¡£/¥t§Ûª0¬"­1­7¬Î­ª±t¸íÃ΂סܿÝmÙôÔOÍ~ÇIÂÏÀÃÁ}ÅpÌ?Ô ÛÂä$ìóœúˆÙ¾ 6 æu`ýôܹo ï!¬#%ä*È198Â?_CßEöEoC®A?f> =:ù8c5*1Ê/ø.©-]+®)µ(«)P,Þ2r7m;€>o?ô@w?Í>Œ;î8k4a0Ñ.¬-ú.â060õ0#-3(j"óÚuT T$w()ž(#-pq ÉúSõšóçõ2úé ·Ì+²7–â [ÝÈíüförñìÒéç³çáê)ï,öxÿj䔨øÝ´æ pÄöüD÷ïèæ§ÛÖÑÈcÁ'»1µó°AªQ¤ž}šÕ™Å›ò¡n£´¥,¥&£1Ÿèœ›œ ¡$©z³¼&Ě˒ÐMÓóÕÛÕÒ{Î$ÈXÃLÀhÀ<ÂåÈÏÛ×Ü÷áxåŽêxñaù~:Œ ^‰Æ&½ÊR#—)ÿ17r;Þ>˜@AOB¶D#ESEÓE4CÔB@@=‘9ß5./Ô+ú*N*®-1Ö7ÿ=ÅB–DØD@½<7ÿ6979q<~>ï?¥>:(4Ë/,)Ù%›"R = 1!ü%Ï+02¯2-Å&«z Þãþ2ú¥ù£ûBþvV Ý €ì\%ã*£d ûf¾ù1ñê)åÜåÇé€ïžö*üŸáa éëHGdFÊd Ž6&ü”øñçèáÝjÐðÄ’º•³G¯®®°®Ð­ç«÷¨Ø¦£â¡ŽžÞ› ˜–C—2›Ú£×­¹·Œ¿Å{ÉfË«ÌrÌÊ<ǚİÁÙÀ¿­À>Á¤ÃVÄõÇ"Ë Ñ×ñßÌç!íòröùûüÍþ+P/p ™j¿!U%3(±+†.81H4u8CÀ9t2A+%U"m"F#Ý&š)³,î/Õ1¤230õ.Œ,'*K*g,±0†5?8û;G:î7f1¤*|#óZ @"ü'»+G,M+o)œ&m!š&š c¹ÿÞü+úø<ö—õ4õDöñú_ÿš þU¥Wá™Âû.õ“ð¬ìèCäçâxâäèÝðÄút v¢ ðÉÇþOj5 …§û¹ðË䩨|ÎøÈÖÆÅŒÅMÄK¾¹Þ³²¬ä¦W !œšé›³Ÿu¤k©Ì¯î¶»gÀJřʢÎÕÑQÒSÑðÐNÍåËÈÆHÅåÆÔÉCÌ|ÏäÓœØLÞ#ä›êððEóÖõ£ö/÷KúþeÁ ¾ƒ÷¦Ô2¡£&‹-ã5{BƒEÙG‘GÍEïB @d?’:Ü3¡+þ%Ô"Ø$'¾,’1Q4Ö728ó:ð<Û>I?,>ˆ<38u3õ/&*|&Í$Š$%'\*",Ø/­2 3ð5 54}310{,x' 3wƒÃfüùøkúàÿ¾ê ~%gþ'ÉM /ügþõýÔýÇü¤ù®õ½ñì‚èÁæ¸ælçsê0ï[öý…`é¾ÂË79VÞã æ ´[ÿ…úpõ©ñ,í)èÅâìÛ Ñ¼Ç˜½M³Í¬@¦â£¥¢Ä£á¦É«G± ·3¼¿¾Áê©ÃRÄ•Æ¤É Ë^ÍÍ8̂ʬÇÌÄúÂwÁc ĠÉlÏQÖÜáCåƒçØéåëë êpéYé ë.ðA÷ó òyÉ´R1!Ð'Â-«3T7é:};;/9¬6°2Ð/2+k(u&±&3'7)÷.(37O:$;ö<8;c9ñ85>2.Š+>(e%ß#¥!q݆ Â#'k,0334É5,3Á1 ,Á%½ÏÒŽû"ùùÈü‚1ó¬ „ N n † & _ … ˆó+óaÿ|ü4øYóœíuç4áNÝÜ_Þòä­ì1ô‰ü¨ˆ ˘ñ< þ¦³z÷¨ 7þFfÇ®ýG÷¥ï–åÙ%ÍIš¹Î³®Æ¬û¬ö®?¯Ù°ñ±–²W³Õ¶ï»zÀŠÅpÉuÌÍvÎÎ ÍʗǺÃM¿¼õ½#À¡ÇFÏFÖ»Ü/ß6àÞÖÝÜÜ"ÝõáµæVë¾ððõ÷þúÓýÍþ£Ž x`#µ Ò&Ë,Ç26ƒ99ý96›2-Ê)}%Ã$U$ý'L*m-q042Y4H6p7ò9w: 97Ÿ5¹3{0Á-ß)ï%] ç+ÏŸ"g(é0˜7B<=º<@7~0‡(† =É; ¥…Çv"ù¨9iÉ—  o ƒ `<âüÔöÆðpéåã4ÝXÙØØ§ÚøÞ¿ã.èîô)úÿª¨i  „ í Ô s _É  _!¨ ,TþõÁíäÜÛ·Ò©ÉŸÀݹ۴± ®ª¬›ªÇ©+¨©©Ñ¬q±@·÷¿<Ƅ̒Ï%ÎnÊÛÅÄÀl¼lº\º–½ÀÞÄÐÈéÌ•Ï3ÑcÒ’Ó)ÓpÓºÔÄÖ»Ù¨Üþàläçgë&ïònõ,öÒøùÍüæÓL1þ›&¡+Ý/Ñ2}44=2þ0ÿ-å*¬(m'F'='è)e+–-ˆ/"0ã1ü3N5y7¨:¼=L>»>Q;5].¶(u"}.©ÖAc  ™h¡Ší 0  –΢? ¼ žú÷õ{ðzë¯ç6ã+ÞÛ=Ú|Ýâ~é°ñÑøÜþ`Þh,E!î  à™1 •†ó¦ªYžãùòEë±åÞ×ÖîÎ Ãÿº+²0¬®ªªk­?²-¸_¿ÅCÉÎËÔË›ÉïÇÊÅðÄ’ÃRÂÉÂêÃxĸƥɡÍÏ€ÑÑÙÑbЦÐÞÒ Ô%×}ÛJßµã±ç&ê&ëoì‡í”îjðòØöªüÞ ª²p$"*µ/2=2ð2À282*3<4‡4’3ð1æ.Ó,¤+g+Ó-Š0j4Q8<åA#D¦F4E­Bô=Î7/Í(}"C tE#¯*0í6—:#;; 9S6ˆ3Ñ0,2(o$” å–#> “ç&ˆÿŠ܀ 6 ç ò šVm ½ Ícþ¿÷[ï–èˆâ.Ý­Û™ÛÝBàÅäÐêðõøöúÊú´ùnø`ø…ú±ÿ < ¼5´éK KíXÆ X - ŽÒý?ò÷æƒÙnͨú³´Ú±ž°»±v³Ñ·"º°¾IÁ¯ÃS“ÁPÀ¾Œ¾I¾Ú¿×Á›Ã&ĆÅËÆÆÆÆ^Ç'ÈNÉ¡Ë=ÍBÏ·Óp××ÜVßûážáß\ݘܸݭá]æ~ìïôTûB© ÜZoù#K'*Ë-ß/ /¥.3+(½%–#"'!•"Ê%«*¨0ú7p<êAC7BE?:Q3ó,ó&‘ Òfo{ª j$q(R+o-n.â0,1A2€3=31ß/g+e%¹ü½ _ÃŽÇ7þûÿGT" ÍäýDÑLŠ ¹iþ¹öâï*ècãßáßHà–äèbìîÁïóïfîUí»î%ð&ó÷ø•ý°¤Z 0 v Â’Þu_!Ù,·ûaï£â§Ö#ËÓÃà¿m½³½Í¾Æ¿¦ÀJÀ†À|ÀtÀàÁ”ÂÂs¤ÂåÃÙÅWÇwÉ|ÊÉ×È>ÆTÅÄäždžʀÍõѱÕSØOÚžÛ¶Û³ÛYÚëÚúÛÛÈÝ‹ßâ"å©ê9ïÌö:üñ Æ^=í%k*².b0f10/.+"( %# "z#t'P-F4¤;ôBmG0HµGiCß>9"3ô/m,`*'é%¹#Ý"¤"¾$k'¸+Ý/°3 5?6¤7À8­8Ù7À5Y1ú-¹(í#ñr††½ oxØIæí9 íA JJ ’û¯õ„ñEîHìNëuê³éÍèUç æå}åÝçèõëZíÎð9ò²õU÷¢úüpþZA È ~óÝ"÷%$¶!E\~ ÿKôié¾ß ×EÑb͔ʾȳÇőúÁo¿l½Æ¼ÿ½W¾ÊÁ{ÅÈ ÉøÊLÉÆÛĤ›ÁÁŠÂÄÆfɵÌÙÎþÑrÓ ÓîÔ¡Õ ÕqÖ8××ÈØfصحØôÚ/ܶà¢åwêâñ”ù: ¹%v!é'ü+ð-K+Ô(#‹7ì~j!þ&**Ø/Ú4î9‹=º@±ByB^@º=f9‹5i1 -')S%ç#Á"|"3"Ë#Ù%A'Š*]-=0¥3Ö6 6’6a5­42W0>-X)™$Ø;¥»ÿÔ[È Äo=é'óZ‰Ú Á_¼üPøpõ6ò¿ðFí釿5ã|á®á«ãFæé ëÇí~î,î^íÞíKíCí¼ï…ó*ø\þ½iÑÝ!¶$m$£!‰ÃÅ ?ìøVñë å¡à}ÚÖÕGÏrÉ—ÄÈÁ¾½‚½¸¿ Á‰ÃàÅøÇ+ÇQÆ‹ÅfÃÁÁèÀ¹À$À†ÁeÃpÅ©Ç]ÉMËcͱÏlÑÒ›ÓmÓ¶ÓóÔ«Õ¬ÖöØEØÔØHÖ×ÕDÔdÕnÙœá9ê°õÿ¿ +&V"<#,"×! >þìvÊU!¤$³)S.Æ4{9G<þ?­@ÞA@@>ˆhCESE.BO<Õ5<-%Î3Œ›Â¨¯è!‹×/1!Hì´¥uØ ­•ý9öØñÌíÐëŒë?ì<îPð`ñÒñýðOí7éä¡à˜ÝŽÜ6ÝBàDå)ì.ô$ûû æ€ì&÷çq7Kbײ+û{ôdìÒäÁÝJÖîÒgÏI̶͆ÌnÌ3ËÚʪÈÑÆýÅÃØÃhÄÄèÅòÆýÆàÆÄõÄÃêÄòÆÑÉÑÍMÐöÔv×OÙqÚyÙ×sÔYÐ`ÌÇýÅ6Ä<ÆÊºÒ Û%äí9õžü…Ãä,qÈÊ=kãŒç´Ã´ %y+Y0ß5Š8:{;V;>:¾9à9(8’8:7ˆ63F/”*ß%÷!6” Ý ~%ç,Å3Ù9/=>Ü>B<8}3x-Ù(X"Ä 7€W˜k Ó n 9  2 só´w_€E Ô­üLöŽò5ï–îÌïƒñònó òïUìçÎãòàbÜðÚcØ"×Qׂ٠܆á‘çÀî³õÂüxæ´ ò sþ‘*¾O Ì+üô{í³ç×ãgß?ÛxØÔÀÑrÎ)ËǮŰÅÄÊÅÅ'ÄÔÄ`ËÂSÁ=À¾ï½Ã½;½l¾øÂ#ƌ̢ÒXÖVØõÙÖÂÓ]Ï^Ë8ÇaĸÃ,Â$Âà ÅòÊóÐåØÐâëSô,üíó v + \ s X f ì_ÜiL|$Z(š+Ù.0”2r5 7ò:Ò=û@vAX@E=78-2#,&¡"\zÚÓ"Q&Z+(0Ï5Ü9½Œ:æ6¾2†/\-#+B* )(È(q'ì'â(X)Ê,Í176:–>@ @0>œ;'5ó/Û)±#¡q ï‡ëÔö†•ÚCã€f 4 ó³Â>Ó2ÿŠþü`úO÷ºôýñìîêåàá]Ü]×ïÔ†ÒWÒÓ`× Ü¼äìóÛú¸ÿÍyÓ ýÃ=[ßQ HÙ@ ˜7ÿBùJôï®ëiè˜æ‡äyâiàPÝgÙëÖ˜ÒµÎÓʼÆêÃËÀë¾(»Åº_º•¼îÁÇÍ—ÓF×úÛSÜ’Û~ØSÔHÏHÉÏÄéÁ5¿6¾w¿cÁ(àÆÑÊ~ÎËÓDØÜûâçPìÇòÂø_ý<§´S§Û´Xª v¤ä"¹)Ù0–5¬8ï:|:Å:X9æ9z87c5—2ë0,-F*3'ý&…%ó&Î),l0²5[9ô=^@fBbBºAö?9ô3[, $°ÙÝúƒdŸ{&<Ýrí(ŠáíjÜE v G "Y¸u^Í™gÿQüöðKéIâÛö×8ÔºÔÔ‘ÖxÙBÜàäÇéŠï5õIûzÄ ñYÞ0ùåy ² /7sýÇú/ö€òàï*ìDéÈç`äââÞŽÚIÕfÐɜ–½k¹o·B·ßºG¾¡Ä+Ê]ÐÔl×dØOØ$ÖÌÔÐýÍ®ÉàÆÊÄŸÁaÀ®À‹ÀîÁµÃJÅÔÈþͼÓÙà«çÍî}ôN÷úùÝú~úeùèùšúYüÿÈ5 ÒlJ!Œ%é*f.Ô2Õ6­8±9)8û7ù6J4B2x0-h*)'$Ë#~$&–*ø0œ7T=mBDÑE2Cƒ?ÿ;¥6G1,•(G$£!–¡Éš‘¾ã£vRØü×f x  * · á ¯ Ä Ø §¡'þ³ù¶ô©ïéDãÐß>ÜPÚœÙ^Ø“Ø}ÙÚñÞiâ‰èî£õ”ü¢} ÷4OR¡n“šîz ‚?ÿÑü¿úÔùuø7öÙô¸ñÂí³è0á§Ú(ÒÙËÄÅ[ÀÓ½ó½¾ÀýĺÉÍÄÒÕÅØضצÕîÔÒcÑ(Ï¬ÍØË8ÈiÅWÂ2¿{¼ÿ»¦¼l¿CÄʬчØJÞ=ãæÀéêûìýîæðNñòöôæö³ùZýIªÙ õŠ©"ª& *˜.º2—5õ887C4L/ç+š'w#º!¦ Ù!‚$'Ê,É247¼ê<8q4…1#-ø+Q)'$ß"‡ #+vì {!Œ!°!SçþÀtW˜G † ™B˜Ñ ³ š ™Ãîþ”úõ¨ñìEçsâÒÝÔÙÇ×ÖwÖÚØËÛåßõäMéIï;õ6ûjP kü€¸ii*§‰ ÑâËÐLÌ%XþNúkõDî'æÝ¦Õ¿ÎäÉÄίÂÃ2ÅMÇþË$Í}ÎþЀѱÓ<ÕLר?ØnÖöÔÐ4Ë\ÆÁu½ô»¥»E¼½ßÀÈÄ\ÈͲҩ×.󦧮â_ä)åoæzç¦é+ëzîðûôöàúýãm­ ×p X',Ä14Á5õ5Ì3¾0˜,–'Ÿ#´ üì Õ#À'É,p0Ø4˜79Å;¯= >>E=h;«9*6C2’.¢+3'´$¦"w!e Û!-"-#X$‰%)$É#h!)ó´Rާ‰ÒŠhû:  Çâd i pôüÝ÷+ñwì*çâàß“ÜÐÛÙÐÙÙ°ÛHÞÒã„éïÈöÇý°Ž -ófïé0Þ Ã ; T $ Ò  J û d Ü{*øËðõèàá(Ú“ÕaÑ2͎ʀNjÅPÄKÄÅ&DZËfÏcÓÕáØÙ/ØöØ9ÖÂÔ{дÌqǗÿH¼X»»(¼º¿«ÃNÇQË>ΪÑvÓÌÖ ØÚ“ÝOà5â™ä®æÁè¯ê‘ìmîoð ò^õÝúí½ þ þ#Ë)ª-v.Ô. ,í*n(%Ø$"™!¿!¾"Ë$|&¶)=,/›3^7:=<«=é>Y=²<9ß6\2-µ)°&ã%;$Ê%A&4&ê'3'&J%$V"” TkÊ»54UÝ ¢[›î˜ñæïŠO˜ IÈþ§úõ`ðZêÍå†àŠÜÙG×î×ÑÙ~Ü àâærì´óãú®G\ a §k5 § Ã Ç • C üò_šÞlý Á pØú óÑí3æ0ß³ÙˆÔ.ÏxËrÈ…Ç$ÇBÈÊÌËÏ·Ó“×QÚ“Ü€ÜÔÛƒØÚÕÐÚÌ[ÇôÄuÁ¿;¾U¾g¿ÀâÃÅeÇ<ÈÓË4Í"ÏiÓ@×7ÚÇÝÍà+á8áà¨ßéßïáhã±èî¬ö!þF?$Ýl!–%'X('ú&ó%m#ê"Þ"!! ý!œ#%¾)©-µ26W9á<Ë>C>:<›9à63I0„.,*)«(ù(Q(P(A(R(Ë(®'Û&º% # {¦š%áiÑ…¹PeÚT`°Á Ô  üÏ÷0ñFëIå„ß§Úl×Õ¥ÖÅÚ~à¡ç„îôøÉü ÿv…PUš9 $ [ XQa ©ø:ŸéL : Øýa÷/ð—ê5ãÛdÕ:ÐxÌïËʈËIÍDÐ3ӯ״ÚúÝnÞ“ÞÛùدÕ>Ñ¡ÍýÊêÈ#ÆÄà÷«Á•ÀZ¿Ã¿ÁÁ)Ä(ÈÌ|ÐTÓ¬ÖR×äÙÙ—ÙØ?×SÖî×ÖÚÝ–âÐé;ð®øeÿ„N%´•¹ "Z#ñ$Ð$Š"ó ˜rÿQì¯!Ž$Ë(§-91¢5…8I9Ç:s:r9¯8>6‹4[1Ê/q-¡+Ö*p***š+A+»+»+ *ê)x'p$¨!òu@|†ÌŽêÝ7@=…€5¨{ͽãÖ- ˜%ûâó…ë‰äOÞEÚ ÙsÙ­ÛQݲàÀä?ç®ësïËó+õùøQúPüýqÿ- ûVˆ e m[ƒæ Aߎe ¶þ}÷Ìðƒèàá-Ú Ô.ÏÀÍRÍÏ`ÒËÖjÙÛhÜœÜÊÜÛUÚ†ÙØHÖÜÕÒ¯ÏúÌÔÈÿżÂèÀ¡¿ÐÀ,Á»Ä+ÆÞʶÎÞÒ.ÔàÖMÖ†Õ•ÔXÓpÒ‚ÒºÔÕ…×ÊÛ4ÞúãûéiïÌ÷ þÜ j´5î „! Añ¹Y® æí É#È'¡+.i1À4¹7r99‡8£74æ2p0F.ª-„,Ù,},F,S,³-r.(.º.í.1,œ*{'ô%l"¤ .f›OZš2b:¿77Ú1 ³!V Ùvý!öþùzòLìççä&áÁà3ß¼àSáôäœçAêí#ï¹ñÝô4õÛ÷ ø‚ùëûÇþöj ¯ (oÎ üe! ûó ë,ã¾Þ0Ús×ôÖVÕ’ÕÏÖw×SØ_ÙnÚ§Û^ÛÁÜ%Ü?Ü?ÛâژعÕÑAÌxǚûÁhÀ"À Á9ÃÆ!ÉsË©ÍkÎÛÏTÐÑÑTÑ~ÑŒÑ)ÐrÐÐnÑ–Ó€ÖjÚþàáçÅïI÷5þù5 { Â’,A€#Õ7«ØøT Û$Š(š+ú/z264H5¡5Ô5S4!2°0í/2-W+Û+S+V,Ú/0–1f10.w,±+›*Î)Ó(å("&«$Ï"†ìRÿ^ˆwÓ¸ `"#™$Â$L"…ƒã züÊú/ó™íÐèèå}ãUâ»ããr䯿æýçÛé$ë ìãïñnó©õFöçø$ùTúþýcý® '¼=uPvît n’ÿø ñÂìç1ã!ßÜÖÚ¸Øê×Ô×Nר؅ÚÜÞßÜá:à¸Þ¨ÛÐØEÔ/ÐÌ)ÈBÅ.Ã`ÂeÂGÂ÷ÃóÅgÆ»ÈQÊÌÆÎ—ÏíÐÖÑÐWÏͨÌPËÉÌfÍ`ÏÑÔÕàÛOâ$épðõøEÿ€ DÌÜ´Kûuiž7/ò,`"'+õ0A3'4ì5,4#31¡0/B.è.í00Ö1K1,0d/Ç/^/r/á0v0Ó1(1S0û/þ.c+Å(U$â!®¨ ÉdéWY H"›%H'h(±(Ô'é%) ¡¯Û ®Þ\ûv÷oôIðì½é°çqæå˜æmç¾é‡ëmìýî]ï_ïòðïñï×ðòõžùþ¢S Ãj[Ž¥ZÏk  ?9ÎûüõùïúéàäÌà}Ý Û.ÚIÚNÛ_Ý ß0áBââ áÀà`Þ_Ü’ÚÖïÓÎÀÊ¥ÆÔÄ>¦Â-Â[ÃGÅÆÞÉË#Ì¿Í‹ÍÆÍ·Í̧ËéÊÀÉlÇÞÆ¡Æ¤ÈËÕÐ}ÕþÜ¡ãHê5ðâ÷‹ý‹àe ó ¸-Í£ú} È;%|"£%Ÿ(w*¸,\-ò//q//¯/ó010Š01/S.l-a,¶,|,Œ-.M/Þ12F2¿2Y1/,©*U'¦$Ú!îaý~ØëÍ!U$•'w(î)&(&3#Žï!U Æš¸ûÓõÛñ'í4é¦ç’æPæOçYèdé¸ê‰êüê)è@æ‡åäëæèŽëÿïÿôçùœÿ± o-O¥p‹!ATó ÌþóøPòìæçÞãÆàdÝöÜôÜàÝÞ0ßsàrá8â?âÙâêá”Þ»Û× Ò…ÎvÊÁÇ¥ÅÃäÃ8ÃWéÅÇÈÃÊóÌÚÍêÎxÎQÍ{˹ÉLÇÅÄÐÄ€ÄxÅ|ÆþÊFÏÔñÜlãôësò’ø·ýQ\X´Ãƒø  ³ mééîI6 ã#W% (*q,þ/¥121Á1//-õ-H,À--C-m-–-R-!-G-Ó.Ø0ð3/4¯54^1Ù-ÿ)^$>fÌ~e\7×%ÖÔCÒ Ï ÊþÇ1ÃÿÁ¿;¾5½÷¾ž¿ÆÁžÃšÅ¦È}ËÉÏ|Ô.Ù Ýjámä­çé*êÛìjí·ï—òõ;ù"ý=`Ÿ 9)³ô3 «¾ î""‹"Ð"â"z!ü!ú"v#¦%f'è*Ž,³.é0Ñ2ð5636ß6`4K1Y-(${!¾@ O"…!i#…%„'Ö)¶+>,a,Ý,À+»*($&#Û!wòúÅóïtÑè þ^ ÿ†ûp÷šôJð©ì|è5ã`ß*Ümۼܸß*ãçnìyò÷CûÒ\ , j:J•¨ž1 ~Lþpû}ù€ø2÷çø2ø±ù&ùTùIøp÷•öÖõ{óÆðûí“éüæ9âXÞ$ÚåØ2ÖˆÖPׇÙdÚŒÛÆÜÛYÙ¼×ÔÕ­ÓÑÎÞÌÉuÇÄWÁ쿪¾'½À¾=ÀUáǛËùÐÓ€ÖÌÙóÜqÞ­àÚâçä¼çê í9ðšô ö¼ùüÄ| @cŽÚñøÿ“S  B ‡ ¨ ù!†!«"J#‚%H'õ+.—257887Ê6¶4‡1}.H*E&`"Þ …yAÚ [ E > é!Ý$B')¤+‹,[+ò*…)'m%®$"ç!9©çknFö:k‰ J ¢'ú ôQïê¢æääOâŽàðà áYâÅäïèZì¦ñÆ÷ëþª ¬{×}5šñ ¤ §„)=þîþ$ý•ýOýOýÇþ;þŸþºýäüFù¨öiòzîé‰åIáÇß}Þ‘Þݪ݄ÝDÝ.ÜÐܰܘÜÛMÚ؟֋ӷБÍ3ÉLÅrÁí¿<¾ ¾3¿ÃÂ2ÄÆôÈÁÊw̯ΩÑRÔÖùÙÛâÞ)ßÁáÈäæ%éìÈð¶õ:ùzý÷X[ ŒÆötbô)\šÜCµèŸ".%ü*f.©24¬5§553Ñ2P0g-ã*®'‹$L!&Œè@0• |!`"<#+#ó%6&e'•(f(M'j&#ñ!qÿJ"fV“(C’¯ ~½Xÿ úçö0ñÁí/éåsâ5ßxÞ=Þ·àäèíîÍô®ú•™‡ 9 vW92:æ ­ ½•™ãÿ­Ek ÿ.¨gÀþ<ûeøZõ.òî¬ëcèÅæiäiâ†àåß›ßà áâ ã’ã¾â«àžÝaÙ×ÕßÑÿÎ8ʱÈÆ,Ä—ÂþÁ}À—À¹Á³ÃZųÇèÊËôÍ:ÎÁÐpÒYÔRÖ§ØÚÛþÞá[ä®è|ìËðdô@øü¿; OüÉ ’×i†¦´a œ"°%e(L+Î/S2b4¦5›4Á2Ô0-*^'»%g#Þ"è!t $ò½\ W"J$¤&´'¢('Î'%×$Q"÷!ò! Ó Ô ü!5 É E!¹ÒÍ IZœþŸøñòòì¾ç âÿàŠà áBã~æjêí‰ñšöú¼aÇ ƒ%  dK * Q~”t6‡e¾ªh ñÿ­ýÂût÷íóÆïnê¬çäxãNã¼äÎå׿læ§æ å;äžãËânàIÝÙfÕàÑÿÎåËîÈíÆÀİÂíÁÀÁ,Á¯ÂÕÄ`Æ7ÇÈÈïÉʾËÃÌ ÎÖÑ9Ó3ÔðÖ×ÄØÊÚ²ÝÖâçXíTóù6ýúˆ0Û ÉOÇãkÊ„žÝá â$Š(+!-À/ê1¯2¿3‡3S2R0Ê.¬+ê(ä&\#Û!à [÷ ' ×!ì#$‰%‹&K&Û&¹&%\$¯$9$$w$Ê$ô$ú$"í!®  † È!L!y2ƒ/> ‰Œþšøâómî„êç;äÆãÚãÀäðçjêÐï!ôOù™þ¢œÙ 7 û £ @ 4 ð  dûÿ‰z.Aõ º‡õ¼þÿ6ü€ù:õ×òNî‘ë¡éšètèCèZéé`é‡élè»çÖæ¾åÇäeâ_ßTÛQ×NÓlÏþÍ8ÊßÉQÈ.ÆÇÅfÄ™Ä,Ä8ÅÆËÉËÍ4μÎüÎÖÎLÎίÐÒCÕ^ØÅÜ àãïè/íQòÙøOýS©u D ’ ­ ë ~ —7k Τ"Þ&6)¾-j0B2313*20œ.*È'Î%;#š"ý#3$$µ%$€$#G"­##¸$ý&>''Œ'm&¿&%\#ÿ#R#$X%)&S'¡('›&Œ%"b¤÷ ®Eülõ¿ï…êåã‚ãœåUèßìËðEó¤öeù/üÝè´×  ž ä Ò ªIþYm^…yò Ÿ   'žøÿèü¤ú÷aôÈò}ï[ìÝë5éûéÌê[ëcì]í íì,êdç³å â“àÞîÜùÚ|×ÓBÏlËÈuƱÅåÅåÆ‡Ç¬ÈÉ*É É¿ÉÔÊ ÊÊ~ËËvÌIÌàÍzÏ6Ñ\ÔdاÞã}è¨îò©öãú¯ýæ³%jZa\ì ¯ y ØJÞ 'l™$¶(ú,º/M0f0C.ö-C+w)þ(ä(Š(Q'Ó&ë%®$B"­!Œ ç å!Š"‡#r$1%%†%$w#[!¸ º z ó"±$Ö&j'b'¦'X'&Ã&å'&š%£#0îÓ ”Íÿ\ùEôïŽëøé~è&è$é5êþí„ðJó ödùæýÎ  è Î {j*âM¿i { ê i º ¼ q G Ö žÄþÂúº÷TôÄócòŠñýñ£ñ7ðâð/ï}îÆîDî í§ìïëÕéüç1ãðßóÜ/ØîÕàÓdÐÎÎÌÇÊëÉ}É*ÉjÊfËßÌaÌbÌËLÊ•ÉÞÉFȋȋÈÔɦÌÎðÒOÖ€Ú¶Þöã”çë”ï¡ô$ø©üÿ†p½·J,QÔ ŽwÅ\!v$&0'ó)`*h++|+±+ª+[*Q(ò&ú$Ž"«!f!]"2#„$À%"$Š#™"v!Q ¨ h ã!Ž!¦!+ À f V!L"Ç$`&-'÷)§+<,k,Ó,=*r'š#¡ÎAO Rãû¾öÃò‚îëOé$è>èÂê»í¶ñ±õžù;üYþ¥ÈÞÄÙz¨UûO%ˆ½« 0 æ §³ a £Üè‘Yÿeýˆû5øÿöVôñúðrð_ð`ðŽðÖñðŠïåïí¬ì.êçÅåá¦Þ>ÛC×üÔ´ÑÛÏ ÌÉËGʤÊÔËÞÌxÌéÌåËëʨÈÅÆ¹Å-Ä=Ä)Å>ÆäÈÊÊ¡ÌÍzÎôÑ#Ô‡Ù}ß³æ.ì3ñoõŽø@údû}û’û,û û¾ý<6  á¤ì§Â,_#¡'Ž*4+m+7)›(U'6&%g$ù%% $Î$‹$_#Í#="Þ"o"H"(!÷!Ù!´!& Byÿl–M F"È&7)Á,”.9.†-Î,K*‚(K&8#É Ÿ‹ëéüaùyôïáìËëDêÊëmìNíÛï·òõ%÷öúÊý×#­tÿèÿnÿnÿ¢ÚÍ%>Ó £ Ä Ã Ò Ó 5 Æ /ò—¼þaüù°÷•ö õTô—ôóóyótó5òøòƒñèðîÉì±êæÑâŒÝÁÙcÕóÓ/ÑøÑªÑèѠкÏôÎ]̹ËQÉÄÉ4ÉÈèÈèÈwÈÇ>Æ·Æ.Å¡ÅàÆšÉTÎÓpÙ°ßúåé“ì;î4ïÌñ¥ó½ö øKú¨üßþkÿ®;*)I sèÿS!?#`$î&3&Ë&Ë&„&l&¤&ž&¦&Ó&Ô&Z%ä%$š$$L$Å%Ê&F&%9#> Õ´÷[z£}!=#N% &‡'þ)„+,»./P/ç/S-œ*Ë&ž!7¿›51ãú`ô´ðNìýëåìíKîíðò“ô@õõÙ÷~øùœú•û{ü4üùþþ÷ÿÞn—¢Á  Š [  < / x  Ë9ÓÈþùý,úâøxö\õôþö ÷Èù†úƒúø­ö7óïoë¬èRå“ãEáSßÝÚܵÛØ¿ÕÔÒ—Ð,ÎîÎÜÏãÑ7Ò%Ñ«ÏëÍnÉÁÆÃ]Á©ÁvÂèÅ\ÈôÌ`Ï*ÒMÕ‹ØéÜlàmäRç³ëîaðèòô%õœöi÷½ùûý¤l¯ Çîü[ü !ÿ#÷%%$m#a"!G ù!F"L#õ%‡&š'-&^$™"« èegýÊ#Ý3&k b" %'.)*â,Ë.°/Ó0a06.ï,'¥!´‰! GPþ³ùÞöóTñðzðð3ðrñ)ñÆò*òèó£ôÍõËöáøøˆøÂùùàû¹þ",Þž ·  — ˜ © ù ¹ 3/þû7ø­÷”÷Ûù'úîüÊýÞýÇüùÑöÑôñûðOï6îÍî!ì$éHå¨áCÜÑØôÖºÕ°Õ³Öm×××ÕÅ ÎSË4È[ÆÅ6ÄhÄuİÆCÇïÊÌÇΰÑ5Ô"×ÐÜSá åZèðëÍí:íÒîYîððÄóZõùøÑü*ÿUeM• ¶©BKmµ‘ÃÅ é"”#Ò$W$Â$¾$Ü$®#ô#‡"¹!V +©šÅ:èÒt"“K"%¾)3,$//19220¶-Ñ)›#ý ñ àÃküÈøËõ}óoòFò%òÒó9óróUóò¬òRòfòñóìõ!ö+÷©ùÄû×ý¨ÿNÝÔ¸5— : Þ 1 ¼ ?Ö þ"ýyýÞþ´ÿ\ÿÿ!þü€ú¨ùNø…ø+ø‰øÒøf÷%õxò§ï>ìèxå âàÞeÝÀÝWÜûÜçÜ ÛÚ.ØÕyÓÐñÏÍvË¢ÉƒÇÆÆFÅ,ÄèÅiÆçÉÔÍ8ЬԡØÛUÝäàâä#æ÷éÈìÉï„ñuòóó¸ô½ö…øPû6þØÎD ˆ \F6ÄþÒR÷ŽÈ!z#8%&X' &×&&%E${$)#Ÿ#€"ù"!` ´ 8®¹2؆{"Ï&j)ÿ,¹.å0W1x2*1²0-()=$vtW Oò¸ÿdý*ûËú)ù7ø/öœõó]ñ¡ðàñdò¿ôËö®ø ùùøyøø:ùûiÿ2Î ž Ç í  ãÞö—ë TãKÄÿ@þ$ý²ýMý=ý·þkþíþäýèü"ùhö^ó:ð ítëHé”èæ˜åoã³â*à4ޒݓ܇ÜCÜ%Û«Ú^×ÐÔNЋÌóÉkÇ/ƪÆÙÈÉ<ÊÄËõÌgÍ.ΩÑÔ#׿Ü6àUãÛæ ç`è¸é²ê™ì1î[ðwò÷õËøüE%Ð 7 •0Ò«,äUMáÎ j"#Á$E$#‚#,##T#´$ $‚$z$;#V!ppb_•#ºçøª "—%î)|,†/Œ2$3T3š2.Ø*¥%ÐZžÞæ Û{íý²ù¢öNô'óUóºôÈõßököõLóŠñ»ðÄðŒñÞôIöñú?ýãÞZEûDXöøV2¸ Â)LVþšýâþ<þ×v[6þ€üTú0øö õŽôòTïÁì£éÈæðäXâòâ¢âàãEãœã/á“ÞäÛÆØÇÕ°Ó“Ñ´Ï­ÎÌ?ÊpÉÇÀÇBÇ2ÇÛȵÊËÄÎKÑÁÕsÙt܋ޢà!á|âwãråæÚéëÇî³ò*õûùƒý“ƒþØ " Ì õòz/ó†eO®BÓ ‡!"#p$6%M&&ª&Õ&%Ù$ê#•" ‘Ú+=Dt@Ĺ!M&0+// 1€2 1/9,À+)È(Î'b$÷!1‘Ï xp ÿþ{ýçýkü:úPøõ¾óÄò ñðêñÁóDõ_÷ùû€ý‹þÙ0M€ëœÁ ž  s õ É V¦¶»ž·H¤Óñy™çbg,ýù õƒò×ðÆïoîXíKìƒëcê`é¡è­çDåÐä?âoàÀÞöÝ0Û5ÙDÖßÓÀÐËÍÆËXÉ›È{ÇúÇøÈ°ÊÌ ÎÐÑÓNÕËØÙ‘Ú|ÛHÛÖܪÞhá!äç°ëÉïœó_öÉùú½ü¤þŽžÞ¼÷ '_2–l®7kû” Z!ß#A$S$È$¹$¨%%Ô'(K(S&¡#Œ›-xe!.›È"k$’&('e(A)‚+8-$/0$/™-ß*Á&F ãV`ø£ × çuÕòGÿvü0øEõó ñ‰ññ·òcóóÑôTô_ô¹õ"õ§÷Éúìþ^Ï9~¡ã\\ëÖŽŽT¾QKŽÝȉÍÍüM“oþöûÓùZ÷‹õ¿ô¬óæò¨ñkïüîëìê‡éÇèµçÚç:ætåÇäžâààWÝHÚ5×1ÓËДÍõˈÊÉšÊÊãÌ:ÍÆÏ?ÐÌÑßÒÜÓ–Ó²Ô\Õ_ÖÊØàÛ—ÞÀâOå¢èÆëêîQðŠònôÖ÷9ùÙý-ŒáØ I x0R ,kÀÚØW"U%P(*Ó+Š+ ) %Ð")éý1Z07y³7í5v Ÿ#„'*ª-¡/ã1#0ž/`,ä)^%“!¥–wÊ!qL äɪÿüvû2úIù'÷ˆõÛó­ñÆðãðçñ²òÂô³ön÷äúû·ý'þ·TÅj1Ïå³è?5“L}ô4ѱ%*é·øÎªH…ÿîþ%üuû&ù€÷ýö<ô{òÌðìîòíšìmë¡ëëgë%ê´é„ç¢äëáÜÌØúÕ¢Ò‘ÐqÏhΚÎSÎÕϰРÏýϱÎãÎͺÎUϬÑÛÔ8ÖbØ<ÙöÛ•ÝgàãƒæÖê„îðÚóô”öööøQúÑþ$pû ™ˆ2 Ø€g"”"H%q'Å(e(k'k&.$Ø#Œ"¥!Ø ÛÃF÷u¹5óþp×"[&u*+,V-),Ú+Ï*ô*U*9*")—(B%Ó"³êa°GÓ ÷ &y ÿ\ûûøö/ôÉóhò~ò[òeò¯òòòûó óeôeõÛ÷ÍùÎüŸÿox5¾/Ɖ‰~Ù¯j©öP³Šð{|øpc¾0þüLú4÷üõÇóûòðñï¨ïEï­ðððžïƒíé“å~á Ý3Ú—Ø×NÖ‚ÕÀÔöÓéÒwÐÂÏqÎ8Í»ÎΈÏ6ÏËÏÆÏ“Ï’Ð?ÒOÔîØ«ÜÂàƒäæzçòééÜêôìZîøò÷÷‹ü’Ž«ò z  : €!Ò\Ül!º"÷#¤#¿#×${%'((Þ)l(y&X"òâ+MšqȱH­ ß" $%®' (š*g+î,Õ-ž-Ø-6+ù*(K%ê#œ!º«É@qO ýf€þŠüDúºù*øöÖõ/óýòáò6ò1óô·ö_økúÔüûþüƒ[ÞÑdsì²J³u´%“¨¼¡¡ŽSÿÞ¥Óý·ú÷ñö9õbõXõÃöö<öƒõuóCð·îëñé¾ç½åµãà@ÝÚÿØð×qÖ*Õ­Õ†ÕhÔõÓ½ÒOÏêÌøÊÉzɂʶ͔ÐÚÔÖ­ØÐÚ=ÛDܲÞßláÒ俨êúîòóm÷‹ú‡üÊþþ´ÿÿíâ;¯ jŽ?º!=Q(ž+!´$´'6()(b'%Þ#‡ ýÿòWj¥=M·FK¡!Î#Ô%µ'W(Ý)³*-*Ú*Õ*å+*¢*>)œ({&u#» ‹kÕ{Eµ ;‚^±ÿþýqúëøOö!ôòOñ}ñuñÕòøô@õöëøvú"û·ü²ýýü°üöý_ýÊþÔÿÎÓ÷‘’ÿ©Fs±•Š&¯>OþqüúÜù¾ùlùøìøh÷`ödõô<óiòàòŸñ~ï©ì¬èíäìá(ÞoÝܜܻÜßÜÑÛðÚRØSÕxÒnÏiÌ,ÉñÉTÉÃËŸÎÐHÒ_ÓšÔÓ¬Ó2Ó'ÓïÖVÚ.ßä#èlë—íâï…ðwñ™óLõžø”û¥ÿ2{½7<d 0 È ~ˆ`ž8·"A$%³&g&È&Ä%ü%$6"é!7@Xs1ëì‰( Ó" #$%.%ÿ'(c)^*È,G-›.‚.m-˜,*'¬%k# wÓEBäp ÒvY=þûYùN÷žöVõæöu÷FøØú0ûûéûËû úÔûûñýMÿ d"˜…ÿ þÏÿPÓÆñ¨ž ‚˜'d;Bÿ7ýOûµúÓú ú¸ûUüûÛû™útøeö*óvðCìÆé}æýåmä’äÖåråéå¡ã÷à²ÜCØÔCÑÏ,Ï%ÏÑБÑ_ÑTÐîÏÏÎNÍC̹ÍhÏ2Ò$Õ¯ÙÜ Þdà3â*äåòè½ëÓï<ò‚õšø&ùÞûþýZþVÿ|ˆÃD! ƨÂ7R\­!P#C$î% %ü%¤%6$". z„%ñg´yõ™3½ R ±!œ"Í$j&\(c*E+ ,Û-«-¡-h- +ê*<(v&r$-"= 6÷G"'¥ ¿sÿ"üŸûjú£ú:ú7úùÉø•ööõûõ£õ²÷ù·ü ýôÿ%ÿþvýãý9üéüÄýsþþ¥ÿÿ7ÿ„ÃáJŠLÄÿ‰ýgûŠúyúOúºü/þ ÿ³cÿný'ù˜õ²òîìëëëŸìì”ë‰é_æ£ã;ßEÜ¡ÚøÚÙ³Øà×ÀÖÓñÑ¿ÏÍhËùËwËeÌXÍÉÏ`ЭÑéÓ"Ô3Õ›×{٬܈ßÂâöåðèÐë[íøðtòBóêõË÷1ø{úžüîþèÄþm [Qü„à "&"ç""1!_ ³ 0Ú@ÈyÎ>ùî Œógô 7!ì#â%í()k*²+‚+¥+b*»)í)³* *8*3)']#/ hìlû!ŽþíüYúøÓøQø½ù¤ú6úàû<û§ü<ü³ýmý×þ<þ:ýðþ þýóýký0ý?ýOýøÿ”µX, šV-þûÂú²û”þ7 ‘Ó´ÿ£ü^ù7öºõiôžôEôÑôšó½òrð_í˜ê¶èiæ°å¶ååPäSâæàݾÚÌ×¢ÔžÒIÐWÏÎx΀ÎάÎ]ÎÎ<ÎsÏLÐÕÒáÕxØ ÚåÝßà!âÙåŒçséËì î;ðÀó0õö”÷wø\ùÄûtþ$Y  ;ïU°1ÀZ|€à  "Ë‘y Ùç2¤Ì¸â÷!ì#R$‹%%%%2& 'Û*>,ô/0/Ã.¤,")h&©#– È9‰)<A • Y,•Pÿ’ýàülû®úÑú9ùáù©úúsûû¯ü²ý§þGþTý÷ü úŸø¬÷©øù‚ü€`³Yüà`;”ÿýdüßþÿÇÁ¡œÂ.ç#ÿZýüüýüûiúàùîøÓ÷ƒõ§óNñ$ï í­ì×ìhì ëAê²éoç™åoâŒß’ÜþÚ?×ÖÖ9Ô–ÓJÑõÐHÎÿÍÕÌãÌ–ÍͱΩϦДÒÓËÖ?ØåÛ¥Þ]áBä æUè¡ê­ì@íÈïðAñÛó½õõø<ú³ýÍ5Ü  ¹u=Ë6 •ÔßÅø!€"!" £–‡&üú©– É!B!& RtòÈŠ!!"÷%œ(u*Û,Í-¿.w.Ü.8-¤-,*‚(]%þ#q ¸«uá­ È žæ`IöýúüùLùú û›ýÄÿÝ;ÿ‰ý*ù®öÆõeõ%öiøòütÿù!ÑYAÿfþ¥þ±ÿhuîËA}ho¤¤»åœÙÿ¹ýÄû+øíöæõ•ôó¶óSòÌñ»ðEïîì±ëÛê×é çä½â6ß5ÜbÙë×iÕ>Ó@ёЗÏËÎïÎ>ÍŒÍ"ÍÍQÎYÏÕÒÔˆ× ÙäÜ«ÞéáGã—å/ææèËê#ë ëÛìƒíÆðóp÷˜ü¸¬‰  ™ IiùéÎ=|¸BžïÚ© Î!g!?! œ zÏ ÅBÙ!þ#ù&X(š*$+},”-p.}/‚0‚0Æ0".ß,¥)u&q#> 6\ÔOºa£ ‚á»þÔýjý¥ÿ Ê“©HpþËû›ø@ö+õôõöuø­ú©üùÿ0ÓÀÿÅÿþ­þ*þ½ÿ| ”¢6ÿÌÿŠÿ³kÉ/;)o±ÿóþü_úóùƒøŽ÷©ö£õ‹ôNó^ònñ´ñ>ðòï×îØíFêûè©åÇã8àgÞÜhÚmØ{ÖxÔMÒcÐÉÏ·Ï#ÎËÎÍNÍ^ÍûÏÒ$Õ9ØêÜRß à±á¾áèá~álâã²æéjí#ð­ófõÏ÷—ùBû¾þ«8 Ï R ’‹.Å@ETèU b!f!r!] ÀéóP=E•ù=Ô ž"$#'6*‹-¯0w1ï2*1,/™-¸+Ð*e)ª)ª)Ø)ÿ)x'[#®ØBQ ‚ܧtÉ ˜iE!þ û“ù´ø±øÅù*ùÖúaúüû¨üfý{þ$þèÿ®!¢OÿÞÿkþÝþDýþýçþ?þíÿüñÈK·É§c]=ÿºþü0ùóø4÷:öÈöƒö%õ’ôˆó˜òÒñðñXðzïbí±ëeèØåñãà?Þ܇ÚÖÙ‚×þÕ¢Ò·ÏÌÌ»ÉãÈíÉ›ËÓÎAÑÓáÕ­Ö÷×‡Ø ØçÙÚOÛÛÝßBá¼ãìåœçØé¤ëbí}ïfò5õÑù)ýpÞ€ ³ ” š&õUû•‰. aÒ ×!¨!!7ãCqP`ئ#œ',*€,g-!,¹+›*ò*)Ø*v, ./í1(0Ù.Ë+H&Z õ.ͦTì1ƒ¸ [ Ì z ¶V®ÿýˆüKû(ú<ùJù"ùtù€ú{ûªüÍþÿxJÿ“þ­ýªýüÜýüùü¿üÎüÈüØý‹þßdît”)*€pVºþéý¯üDûù¢÷íö·õíõtõ£õÛõõ­ôçó ðâîjìYëêéDèmç äþâÞ]Ú§×ӜФÎnÌóÌ8Ì=Ì[ÍMÎ9ÎôÐ8Ñ ÑÌÒhÓÔlÕì×ÎÙÜÛ|ܼ݆ÞMß)àGâ|ääçñë±ïióVöºù²ü;þ¨‹-–> \ @õ [^ûGñ¯ .!þ"Ã"Ç!ž» %Q† 2L ¹##%&G&N%™$÷$É%L&ã)M,$/'1†2·2ÿ1Ë/»,í)|& "AñÓ¯ô& ç V{%½ÿpýOû½ú~ùñùëùÓúYûcü-üíýãþÿ*ÿÊÿÅÿŸÿýóüéûßûtûjû½ü¾ýäþÒÿA5 Ì&,Ñ2ÿKüsú‡ù¤ùzùèúmúùâø¼÷_õÇô/òññðñkñ.ðÒð®ð/ï@ínê¡ç´ãßßNÛsØ$Õ–Ô ÒÖÑÚÐùÏïÎÁÎ(Í¿ÍbÍÀÏÐÒxÔlÖ××ÖùÖ`Ö×_ØûÛÁÞuážä-æèRêÀíOðIó´÷úþdÎ]6Xô — ¸«,¿ ß!Ã!7é–Rš@М œ w qÙ³ \!#%—(Š+l-¯/Q0V0p/å/M.%, *‹(w&Q#z!z8â•‘!ýf ® ãýж þ,üzúüú ùûúÎûõýjþšÿsÿ·ÿ^ÿ/þºþ•þgþNþý ü4ûùéùŽú û„ýÞŠ$Gz»m_$ô*ÿØÿ!þšþþqþ,ýzücú¥øöÃõjôúõõ•õóöLö”õÛôÓòhï"ëÃèåðãtá»ß¥Ý ÚׇԓÒ=ÐYÏ ÎÀÏxÐ.ÑÒÒÒÿÒíÒlÒ9Ò<ÒÐÔ1ÕÆ×tØçÚ:ÛGÜ Ý@Þ¨á)ä¾èõíñó4÷âú·ûèüûiúÄûü/þÁÐX §7!M–­u4ã7š‰×%HkÜä¾+É š"p$&J(K*+ò-.ø/.Û-Ï+þ* (o&¯%#¦"9 G†ýùt/k;æã ûj¨Ùÿíþèýðý üoû—úîúàû"üIýäÿb”ÿÑþü¹úÙøû÷Ì÷P÷ÙùúÛüðÿ!ÉF•Ø”P Ñç/}âÍÿÜý†û4ù÷ö÷÷—÷Ûø.ø®ø”ø÷öŸõiôšónñãðƒî«ìèÿåmá–ÝËÚQ×ÕÕÔ=ÓxÓÒýÒ‰ÑùÐøÏ¢ÎôÎæÏgÐÆÒ†ÓÏÔÊÕÔ‚Ó“Ò°Ò‹Ó%ԡ׎ÛËàõåæêeîðìò$òIò:ñÉòóAõ—ù9ý9þã -ŸjÎÚµ¤ÕEgè# ²ÉÙ Út(!S#¹& '»)Z*u+v,K-L-ú-ä- +s)7' %q$W#Ÿ#M# "! ¨¯|è'+WÆ ^ ÜÒ<ÿ£ý€üûˆû®ü”þ;ÿÝUwµÿ–ý[ú×øëøLø—ùÌû,üßþ2þÏÿBÿ†ÿ¿EQ±b.p¼LH™ÁÿDþVý}üü ü‰ü*ûËûúùoùBù`ùëú~ú¿ú7ø’ö òàîŸê¬çƒä_âà|ß&ݾ۰Ù^ÖåÔÒвХÑ{ÒxÔ Õ°ÖxÖ^ÕWÓ<ÐñÎäÍšÍ}ÏÑàÕ¹Újßwã‰æJè%ééRébê*ëzí!ïÒòõTø"úÁþ‰Â J çØJ°= #aB³ ‰–a(®’í()ew H"w$Î'3)^++õ,Á,Á,W+›+*Å*r*!)®)a(8'E&‚%2$_"Ý!S+ÿ‹®„* G ¿Ñþºþþ£ÿæAçç1¶nèÿGýîüÝüKüûìû×ûyûxûTúèúãû&ü ý·SHç4Ì•€¹ÁDÎþfü¥û>úùúúÝü1ýšþ§þºþü¥úK÷íõ•óVñuïÂíøìé˜çãäßüÜØŒÕáÓëÓªÔlÕßסØúÙ3×ÅÕ€Ò-ÎÚÌ$ÊɰË%ͶÐ:Ó2ÖNØŸÛÝ/ßXáã ä ä·åiæYè:êÖímðóuö ÷÷ú0ü¾ÿAì¸  ¾¹èòkÃòüÒ&ãßYUØ`º«ò j"S#ý%z&|'b'µ'å(M(Ð)1)a)–)8(½(P'.&8%“%l%œ%®%¹$è#, :AÈ.¸ [a¨æ÷û{cË;… ÌYÿâÿþBý ûvúøÇ÷÷÷¿ø5ù<úÉü*ýžþâ(UŽX:~#þÝýûŠúÉúÈûoülý”þÜÿZÿþ^ý?üûúTùðúùøù<÷Èõ‰ñ´ì»ç‚âÇÞêÜcÛÔÜHÜñÝ“ÝÚÝIÜ\ÛÙV×4Ô­ÑúÏQÍ!ËÎËÀÌäμÑSÓöÖxØrÚ4ÛJÛßÜïÞß‚á²äåðç°éjê¸ìoî¢ñó…öKøõûŽþ ·Ù‡ ¸ „f+~…ÔÉú¦ˆ…›ÔÌ:Ýã÷‰, Œ!"$%¥'()j)®)†(Å'Ö&í&&&»'Ž(ç*€+†,M+‚)Œ'#eÀbU÷˜? s ’ šû¢Tñ¬ÄŠWþiüœû­û2úøúúúäú¼údú?ú{ûü7þcúœÆí ˆ;Ü<ÿóþ,ýˆþ*ÿ^[F þLüsû…û§üÌþ‘{ÑQ½ÿùýdù£õÈñ»íd锿±äãSâúãããêãÒâ¸à¤ÝÚvÖîÔёϚ΢ÍàͪÎÎéÏ­Ñ+ÓÔ–ÖbמÙ-Ú»Û¬ÝHÞ¨àâäåãç«éêäìÈî˜ðàóõD÷ëúfý:ဠ·0 0ײ_FŠè²-d0/Ü̺J!–#V%&&&4& $ÿ#Õ"À"Z"c#a%'")®+B,2,z+å*›(®&P#ñ!OLlCƒ¾ µ ç‰óVdhë%39PþÈÿ‰þ…ý½üèüúëùc÷…õ½õõè÷õûJþñc,40 è:*“¾¤(ôÿlýøüzûÎûNûqüKý†ÿY”tªýÒˆýÃùoôÔð×í²ëAéöéNé èÛè’èç[åÜãÐá‘ÞôÜ]ÙdÖtÓ¢ÑvÏ¿ÎbÍͱÎÎØÐÑiÓÔÕvÖÞ×æÙ ÚjÜݧߵâmäG妿Øç¢èé4ê¼ìÛïbóöÜú‡þLu5 ¾ Sºç¾®@”‹AÌ,×ý¾¨†¿ !6"Ú#Å#Ú#"U!v å!.""¾$ %L&['e(A)¿+G,Ï-¹-ä-M+](Ý%Ý"Q¨ Zû6&' Ñ ®  ö öF …“óIý¸ý7ùë÷…ö”ö~÷”ùcûQý þtÿ²·¹wÜ™N´ª[»zýÙüBúÙú?ûJýÿ@zP>"‘þQúÂ÷IôŽòðMïîaîíâíìëë„éÛçþåyâùà.ÜàÙºÖÑÔÑÖЊϧÏ}ÏëÐ=ÐQЦÑKÑâÒ£Ô Õ¦×ÙÝÜÝçßjàÕáâXâÝããæå!çé©ìËð>óû÷úý3#ŸtS K ¿¦;aB”= „ ÇIüžR¦ Z!!]!j Õ Q   3 °!U"#"Í$‚&¾(Ý+-ý/Š/ß.ò,œ)V%°" ,ü6´þŽÄ¸ Ý   &  ? “ K \ D ØN^þû­ù¼øOøø^ùú7û:ûÜüüLü¿ý3þ\ABNoQœÑÿ8ü‚úèú0ú ú¢ü[þ®œp§_hÉþ-ûŽø^õÆóýò‚ñXðîññCñ ð‰ï‰í”ë4èmårâ‰ßcÜÁÚJ×ÂÕÆÓÇÑÄÐQÎëÍÔÍ}ÍIÍ›ÎØÐ€Ò>ÔGÖ€ØXÙáÛ"Û·ÛßÜÜbÜçÞ;àSâ}äœæ¡èjéÿëÝîXñúö+ùÔþ:H{! ö K Ð Ù ¸  r ì & ó “~À<ì«\. , a MHþ²³!U$¶'ý*‚+ð,H,+¶++*¥*)0'|%_"  Ã!z{ \ ± Í Þ?e'  í ¿˜ñÿÈþný¯ýü‰ûõû$úaùøÃøjøùú'ûŽýàÝ‘!e /Ìž+kÿÑý„û¢úÊú·û:ülþ!N~>ŸfAL £ÿ÷ý=úÔøË÷qöŽöpönöSõÿõ©ôëóœñËï»í£ëPè«æ ã°ásÞqÛiجÕCÑðÏqÎÍÂιÐgÒÓáÔðÕyÖÖSרÙJÚ†ÛÇÜÜÝ|ÝäÞsÞþà á9â~ä¤ç=êeîó÷nû…ÿ;<ü‡Ó×É ' ¼ é / O !ÃÅVª£i¸uÓ¾“¾tÈŒƒ Ë"“$%€'( *.+s,¶-‡-Ä,è+(s% Ž `¹Â| Ãlq¥~¤V  i‰Aߺþäü¹ú‰ø‰öàöö}÷Äù¿ü!ÿçKT¦»[4þ¯ülúãùœùxúûÓþgÀQ?˜¿mí‰Mþ"ü úÝùéùšùÝùIø7÷Jöõôhó¾ótòÝñ«ï¤ì·éIåUáÝRÙÝÖ¡ÔqÒàÑôÑ(Ñ7Ñ¨ÑøÒÐÓCÓqÓñÔàÕú×5ØÙÚAÛdÛáÛ›ÚÄÙéÙVÙˆÛÝ›áå%èØìIï}òyõƒø±ûòþýÔ è¹¨ íœ0® ñ ë‰Þ8H™ø’Äfâ&ÒAš@ƒ!Ò$M'K*–-Œ/0Ÿ0\.î,8(¿$Å žñôÒ£Åïå ŸxW/B @ Ö ¸'þÉüZùöøN÷]öû÷døúyü½ÿüô0¯2Fêtþüúøòù!úPühÿh…™…Auís¢ËÇþfü–ûùÇø·øpø.øqøÇøéøßøD÷{õŸó®ðàí,éiå“á‡Þ:Ü ÚØÖ]ÔvÒ­Ñ8ÐbÐ~ÑaÓRÕBÖ»Ø ØêؽØH×õ×g×g×ÄØØÅÙ}Ú*ÛYÜ£Þmá¡å}ésîòÜöÌúü°þUþ÷þÏþxþ ýiýóÿBÞ‘Š  7@©(–£ßèv¸»šŽÀR´†èiÝ"ü&…*.-K.Ô/..,B)‘&b#. ©¿b0ù ø÷,Ž&çnæ®%Ø ù UïŠý3úÖù&ø÷Âø:ùŠûýc,½f\©ô ýªûÓúvùÞú_ûiüvýÜÿ~­Z¦eäZA޾øu¼þ”üú#øæø…ùúû%ü&ü0û{úCø:ömô{óñPïì‚èðåYá9ܵÙ(Ö¶ÕÔ:Ô>ÔªÕ#Õ¢ÖFÖÐ×WרØ.ØËÙÙgÙ—ÙGØÛØ×IÖ°Ö°×$؃Û2ßãíè¡ídñ^ôšöˆ÷cøøUøžøÜù/ú#ûzý-ÿ6v‘D:Ü ý {¿ôA`ÌsY½% ”(Þì¨H@ ”#0%ê'Î(î)})A(m&ø%c#q!‚ ,†jTP@NÔûÉëWÚ`©-jVÂz à $xÁý¢ú•÷õöŠ÷øŠúàýpKÐ_eüá ëGSþ³ý:ü6üülüœüûýˆþKÿ_©Ž˜Vé­O0'ÈÄÿ1ýäýJýüíü¥ü9üû­û¨û•ûÂûîûûûÂú˜øíö’ó¼ðJì‡éå©áñÞëÜ­Úçٺس×ËÖôÖhÖ½×MØdÙ°Û ÛàÜ3ÜÚ®Ù×vÕ¹ÔÓùÔ>Õ¿ØDÛÊß½ã—ç^êxíyïØñYòŽó®ô>ôÓöö¾ø?ùÉúÌü*ý@þÿÄXž ¹ofP‘ôŸdzã– íSKä%k.`!y"ÿ$Q%;%¶&0%ó%w$# !MB,w®"ôÔo™ˆ¥ƒ+Œ3iö© ŸþËûíúù_ùøûŠýƒZN¨½à|0ˆSÔÿÖþüQû újûü´þ›1ÂI{bŒr X£ëï…[Fÿýäý7üæüÎýIþPÿ‰6ÚÂÿ”þYüjú ÷¨õNòÓïì¬éÌæ‚ã+àÝrÛUÚÙ«ÙÂÚâÜ£ÞßßÅ߬Þ×ÝdÛ:٧׿ÕÁÕÕÖ×ïÚÎÞáã¨æ)ç¾éëÎíúðòÃôIõ}õßõ™õÂõùö4ö²÷ÛùnûGþ$‹€ ” õÔý+/‹Ô „  ~ Y*›DøG Þ%µ!"!é"§"ø#e#"®"J îÿAÈ`RŸ0A`Ç×{&Gˆ,†×Ü £¡þEý˜ýcý@ýýôþéÿîKN¦ž -¶ÒÿßþüšûQûûØü£ýñÿ”Rx™³Âz²¸üúiŽ ÿzþ7ý½ý¼þþ½ÿùófÜ‘*Ö?ÿ¿þØýû›øÌõò`îÁêÊç+ãßáÞéÞÞßàçâãã$â3à†Þ~Ü€ÚÂÙm؇ØØØ_ØüÙ’Ú‹ÜÝõà!âPå$èê‰í1ïƒñcòåó”óëó`ò„ñýñŽòó õõù"ü“3§ e Ä ýc'Ê ä ¼ ˜ / è Æ a÷yG7<q†;,™ ‹!€""R!ª •¾Ap'ÃýAÞáχp`§ 2  ’ds¹þ·ý%ü¢ýýýÿÃâ·óYŽÙë~ ÿøþÒýºýü‰ü+üQü¬ý©þþÈ׊„-lVᙘ‹žÿ²ÿYÿb ‹Ì:‹ØN Ø$êþúVõËñíÚê¸è?æðæSå÷æFæ/æå¹åBä»ãÈâµáOß«ÝÿÜþÛÈÛ#ÚÚÚ‹ÚNÙïÚÚ²ÜÞQá½å*ègëÕîNïïð·ðúñðNïãïÁïjï¨ð@ñšó¬önùœüâ_¾r„ X _ ¹ } a ñ É Eö´  6 ¯ P}{¯RF¼£Àø!7!Ó!ZüHoÀ3!\ºØoLT£ÂØÒc“ãý/¢ çâ`ÿ€þ¤þÉÿz˜sL´üøö%ë ˆÿ”ý¨üRû—úçûYüjý~ÿb})@? ‹6%;•ú“EÅôÿ8þyýöþeÿ¥›”jó™E4?ÿûÓø!õòOïúî6íìXë·ë,êxé$èSçoæŠæ%å„å,äâ|àºÞw܈ÛÙäØÿÙÙ°ÚÐÜsÞ½á˜ä(çéÕìíòîÑîÞî`í¼í ì©ì‡ííñïñAó¸öOù”ýSv!V·6?,?Œ®{šsÞ¾K 5 ð 81ƒ~?•dV£q‘Þˆ†‚dÙÌØ– ·Ÿ†×Ø í ?øQ#¨¯ÝÞ„ëÒ HUÿ„ýšûØúÞûûÛý6ÿ÷Y@®ý;³{•Ö½P‰ÿ×þ¹ýšüûýý}þîÀÈ/+™övÙÙ¨qþ*üú:øö ôò)ðxîïíÍíríFìØì“ëãëê*èÜç“åæã¨árÞõÝ Û…Ú=Ú{ÛÜ)ÝßßíâDä™ç éHëií,îJî{íõìÆëê©êdêØìíòð£óöøöûŽýaþ÷ö{!¯Ì­ö‡Ùӡࢷs$ ˜ ¼Y7LÚOwEZZ ïI­‰ Ù­Š´G‹[³®·LÁ{ F pæ-D®ã`q‡Do@²aÂàÿaþEýiýüÑü‰ü˜üÙý?ýÜþéÿш—å)sÂ¥þ4ÿäý¯ü_ûÏûèüùþsG2Þ4>¾ÑShë[€ÿ„ýçüùÓ÷•õáôtò÷òñoñiñ`ñ)ðÄïÎîDì`ê~è3åñã­áßoÝŒÜ4ۜۼÜÐÞWàã;æè¨êáìtìÐìÐìêÝêé¬éÆêmë?ìjî,ïÃñtómõö´ø™úàýjM9pݯl³ÁçTn<@y2P÷  è¤Âíkdx˜ñÔ Ï¤žä †t ~ÑûUz¨ WƒÅ ¬ ëH_eUü§Á1@³æŽûDè…KVÿþÏþvý®ýüTûˆûDûZüþES[bÒyÌEy_ÑÿxýâüÙüpüý[þ¥5§8n~è¹mÍ_Ÿ`³Þ¥þÎý+ûùÄøÑ÷î÷u÷5ö¨öõšõôkóªò)ð&í²ê“ç[äŒâߺÞ{ÞaÞµà=â|俯è³êêûëŒë}ëUëië¤ëýìiì±ì¾ìÆìýí íêïð~òÏõ­ø6ú·ýÿä¾jÛËy˜³¶ò(6ý$ ' X Þã'Éè½ý%¯Æ:ؽ›Ì æ&‰µp8ãýqûl7Ø A sƳ˜²S9õ2 Ç*9]¾çËoÿëþZü×ûáûúÆúÙûý þÓìûð“Î-ót ÿ¹þÅýÎýžý¼ýÇþ@ÿyÁ™Ž×  ½Ö¹KÖ(ÿ^ýöüÇû—úWùüùØù°úEú‡úù†ø‚öNóNïàì1è¨å©ã âRââJããùäÚåÅæ¡çcèoé®ê´ììãíVí+ìÝì€ëÇë}ë^ë§ìì¶í¸ï%ñó`õ¤÷Òú§ýÿÓñÓ7¸ŸK†þÂýîþþ´n1@ ¢ ØEŠ>²ÈUJ´GŽèý z " \ ) O  i†^3[£ÝK ½ Æ +L-¹KD‰sØÿ²ÓD,âMÿ^ýYû¼únùÌùÃúPûËý`þù® 9)ÐG¸Ÿª~*þ´ý¹ý6üéýý™þžy'v§âÈ"_EÁ¹7ŠšÿýÇüoû«ûËüTý_þVþëþòýâü&ùºö·óîñ)î6ëtéIçPå«äjãüääuå廿àç¸éê@ëmì½ìýíUí„ìàìiëçëJë9ë…ëæì»ícíÊîÿðŒòjôð÷öûOþxý”c¢í¡ÀÿfýúýCýýý~þí0ŠK o 6KJ\¦?\ Í  …à + ( U J$Þz<®„ÁÔž+ ¬ Až€QkY—øË+¿œy’ØiÜÑjÿÄý¸ü%úÔúù®ù€ùáúªû«ý%þ¿-Ê ¾A{yB=þûýªýü|üü²ü³ýIþ=ÿÏÉ—6yó ©Á‚ªÿ%ýþý_ýyý´þþ„ÿ!ÿßÿßÿ¥þîý€ûNùö~óÃñ…î¨ìNêsè¸çåÇå°å³æçSè©é“ê‘ë£ìiìÃííªí÷î4îZîímì²ë±êüëëzìbíÁïÂòxõ÷Žú ýsÿÝD"`ÿ„þyýüüüüüÂýžÿ2V¡N _ É/Q™8a7_ _ t ã pû + ) Í~ìޚ̀lE¤¬ > ÉÖጡ‡D!­ÂAî.¡<MþŠý3ûÂú}ùãù°ùºúsû¹ýÿ®äÈ Ócc*…qÿ8ýÙüƒû€úÄúÍû´üóþ«ÝñÞe>â€Ã¶Çñ‹ÿ€þçþÂÿ(ÿŸ&­K_\Üÿûÿ ýSú¿÷•ô—ò!ïLíiìê®éÁé èŽèjè¶éOê&ëJìJí:îïï¾ððQð ï%íäìàëƒêÁê¶êÈìíÌïáòŠõsøúüQýîÿ †ÜTÿJþ7üîûÍúçúqú˜ûZý'ÿZç: @ ϸ%³tÆ ƒ + 9Çuj  1 Î ½  ÆøØRniÒá · " fdƒÈŸÃ0ë~êÎh­ÄƒÇSBÿþþüJûúƒú,úJúøûTûûü©ý‹þ´ÿ¢ /ø‘Ó‚]o%þ£ý0ûÅúôúúÞûæýeÿ„Ï©Q*20ÞPemu2"ÿZþÝþíÿZy•7^Ká§þ·üÃú6÷¿õbófñ0ïí¬ì4ëêé¦é“é¡êDëgì©îgïòðøñ]ñ:ðãïåîÌí]ìIë`ê®ê“êÝëúí@î¼ðøóiõb÷æúTüý°þüÿ¥ÿÎÿ†þ„ýaûÈúMùcøÁø—ù­ûý´Î§ ’ — û ×`’ i „ e ‚ p£^òÜx „ Y { ay"Zæþ â i¢u§Ø¼î²$2¢š&xÂÿjþüîüû&ú¥ûúôû+ûòü¿þÿ“wj*@r£ÿšýçüóüüüüýþEÿîgVzDpjHôÔÿÃÿ“ÿ̳t@‚Fš kÿÃý³ûùú÷õõTòëð©îCìŒë¨ëë@ëøì÷íðï1ð[ñ/ñõò,ñ’ðÎð#îýí§ì±ìë*êØêüë~ìOíŒïfñqó¶ö)øûûpýIþtÿþÔýëüÌûù¦øq÷[÷ ÷ø§úKü˜ÿz©î… ' á ­ 4 ¥ Š ¼ ’ñÖOŠÖdS d z # < 5=ð-B  m xoˆû{YÃOÿí¢Ù²SƒÝ%öÿ¤ýäü&úàùñù[ù˜úJûWüøþ'³Ö‚¢jêÎcÿýúüÏûåûÎûÑü;ýGþ_ÿ¼~Þ4¢^«!“ Þɺiük©T¢Â´á áÜÿ©ý ú‹÷Äõ!òÆðÒï.íÃící·î:îàïÀðÛñeñæò>òiòYòñð¾ï¡î‹íëöëTêôêôë«íAîãñ4óáötùlûîý[þ2þUý°üû+úAùtøtø;ø_ø&ø½ùÔûý ÿZÓ%h^ ã ¢ Ö Ñ [ Ñ "m”™þ¾ÓÇ¿ò  Ö׬ ¥ Ua™A•„Os±Ü,¬ý³@¡¥;çuÎÿ-ýGûÎúÑùÙù<ù¢úIûTüÂþPÿío½]ÿkýìüâüû¢û´üLýsþ¸Ÿ^¨à­…0ì[ÍD’HLGa_èXÉró˱\)ÍèL@ÿ üùú-÷qõ’óÈòñ$ðzð ð4ðìñ‘òòóDóÞô)ô’ôTóÆò­ñï€íNë—êwéçêKëXìñï+ñ‹óûö÷šù'ú—û•üü@ûÒúÙùø&öèöAö%öc÷dø•ùÈûZý€ÿY:AÑFŒŽ  D "Á ¾Ø2öF Ò i ^ ± Ô ± ˜ · Üs ú§˜<·Gi<×—bˆKË4+¾ìÿýšüIûúSúú<úÉûüÂýúÿ€ö/?/gÿÌþ?ý<üsûóü ü¿ýàþ®ÿ¼'æÌA‰–ˆzep$­„ñÜ8“V&$9ä÷•ÒQSNÿûýÇûUù:÷]õ{ô_ó^òjñìòò¬óœô²õÈöî÷7öõ¬ôóñiïÁî^íëûë~ë}ëûí1ï8ñOó¦õå÷‹ùZúûeû”û`úãùÞù÷×÷öŸöKö÷÷ÙøÒùãûƒýCÿ6O<"/Û DjY`p¸üp_`  / Í f ° £ G à ÷ ð§eê Odî+ “çÖ;t£}ü•þÂüîûÉúiùáú=ûü6ý˜ÿYª JP©Êqÿ+þOý•ýJýgýÍþþfÿJ§ŸE+³‰d ’¸æYÈ›‘ü_Á,£óêòÉò­u(þˆûùK÷õéô´ô?ô<ô”õtö!ö®÷yøø:÷ë÷4õãôˆò÷ð÷ïíhìoëÂëiëØízïñó`õöÄøhùVù¾úùéùù*øÂø>÷mö¬öõ‹õOõ…ö¨÷²ùhû§ýÒô² YYúkÓd9S”9¸™ËÍÊ › ¤ ì O ž O ³ J³7ÈÌš¡Y57•md?*$ÉíÈ@ · ÿóý÷üVúüú úú®ûxü¥þ2ÿp_y ùµD®ÿÝþ÷þvþ!ýƒý~ýÓýÒþ þ‹þûÿ@ÿø#éø\ÞˆcdÁÈÜaB‰®ÜP¾J–ªµÓ  & D  Šdý7ÜMýøûÅù°ø÷ öYöTöØ÷Køøýù¨ù½ú5úEùI÷öö1ô?ò/ðxï!íÃí~íÖîJïTðhñØótôÉö!÷søfùtúTú¥ú•ùáù9øe÷Cö\õ{õõ$õ€öh÷wù1ûsýyÿp!±áš±Ä¶’>Ö}EôÍ'«¸‰•¯   Y Ö ¹ A D„?þÎA´ÿ½cW+^ã˱fÍëÍÖêÿIý¨üUûqûúüûNüýþÿ++–žTÿóÿ¿ÿ²ÿEþþDýŸüÂü"ü ü2üÈýÊþ™ÿÅ­eÄ8”„+ËE³-†#A©_]yzæ×  Ï á ˆ â}Üuþ üDúEøìøZø;ø¿ù‚úšû¯üüûæûQúø­ö÷ôþó òhðòïÂï1îæîøïtðfñƒòÝô‰õ­ö¼ø.ùzúúƒú¿ú6ù"ø÷õëõ1õõ6õÃöœ÷Ýù^ú÷üÏþ“ÿ¼*,ÃDEóƒÁN'?‰ð¸¨ÈÄ]  o U cóD:Ôb¹=ÿˆþ÷ÿ ñ;fšoˆ hÒnþíý·ý-üºünüœüÍý,ý¥ýçþ¤ÿe¿OO:%+ÿ!þ™þýFýüßüÔýý†þ1þßÿß_'òk­Î§Z©:v1A}Ï ”ÛÝ d  á  u u¹{A§ÿ:ý‹üNûnû+û&û_ü1ütüæýJý_ýZü“ûoú-øÂ÷õhô,òûñÑñ$ð]ïÛïÝð‡ñ¨ó+ô¿ö ÷¼ùúú¸ú´úIù£ø¾ø÷4öFõ©õõbõ¤öD÷•ø“ùöû¸ýWþ­Fôcœ”^8ǵ«~× ¨>ð]•e@ 2 Ÿð÷yLSÿ1þFþ"þ¯ÿº<¥¹*/ýTˆ³Éçÿ þý¹ýüŽüYüƒü¹ý_þþ·ÿ„!´6–ÿ™þ÷þ"ýŽý,ýý ý#ýjþþ•ÿ‹pY&¼Nt[þ™*ƒÞÿ´ÿþéþÅþþÿ¬Ã…©] ¯ ~ £  t‹„scþ½ýÍüëüªüƒüÆýý'ý¥ýÑýñýÌý=ü³ûÎú=øÓ÷9õ2óÑòFðÝð!ïÁïïðÍñÞó+ô~õöàøOùùJù¨ùUøÒø ÷Töˆõ™õô·ôŸôÈõ;ön÷·øÛúFû™üøýúþ¹ÿÎZÒÀ³Žs•×"{% :@{¹à ? _$޶A×ÿÇÿuÿþëÿk:ÓÒÆ“b”±:sàéÄÿýÎýIüèü·ü£ý ý¥þLÿ6ÿÝ‹UeDüYÿeþäþýký5ýýeýðþÁÿ'ÿ׃"òaIã*Ó<eg\ÿtþ®þnþ}þÙÿ˜"籞0 / a ä  e U Ò9ÌȈÿ²ÿ!þÙþÎþçÿ+ÿzÿ©ÿ~ÿþ4ü°úÉù ö¾ôåó½ò„ñ•ñNñžñÜòšôõö0÷Ãøöù˜ùÜú=ùûù/ø{ø÷[öšõõõiõ@õ1õšöd÷Pø¹ùëû,üDýOþþÿ@ÿ¨ŠÓö}ÿßÿ´ÿLÿAÿŽ:jÂXÁm²aNOSíˆÿvþ¸þ“þÇÿ ÿ³6ÝGçÃJ?/ =yÿ/þýyüáüRûØûáüüKüóýóþÇÿZÿá ÿ¾ÿ þžþGýÍýKüãünü'ûëü?üÂýýãþõÿÃÝü¡²PÎ °ÿ€þ•ý„ý#ý‹þ ÿ@üÌÒ  ! ¹ Ø D k/ëàŽ;íM‹ÿùk©qí4îƒþŠý/û&ù÷Fõ”ôhó®óDóó©ôŽõõ•öàø ø´ù¶úiúúJù½ù&øF÷:ö¤öõ’õ”õéöö}÷Nø ø™ù™ú´û¯ü¿ýëþÓÿ8ÿ¬ÿ ÿAþóþ{þ%ý²ýyýÌþKÿEî7û’r«üj¸Ó¤ÿZþ½þ}þEþ±ÿ4ÿ‚ ®jôaÛ®eÎáÿøþÙýÇüµûöû¥û·ûâü'ü¨ý:ý™þ þ£þÇÿ/ÿtÿšÿ‚ÿ\ÿQþký½ýeüðüYüûõüü/ü…ýkþŽÿ¬ÔÐ_È花dÿ@ýàý0ýýEýÔþÝeñ‡!… © D ¥ æ £ ¥³íŸj`VWè´§ÆnøjAüp9þžü³ûù‰÷Íözõ„ôˆô,ô~ôîõµ÷÷öøëù×ú6ú`úeúPù®ùSù6ø÷Ò÷Töøö®öTötö²÷÷´ø‰ù†úûÝüòþþäÿ6ÿbÿþOý¯ýEýüÂüØý/ýýÿ=âJ¢ä­4îOh‚§c1?ÿ†þ¸þ?þQþyÿ+ÿágìVWî{ÜÿEþ›ý©üÙüQûñûªû“ûÏûÃüDüãý'ý¤þþ{þäþìÿþìþþ ýOü°ü^ûÓû(úðúÊû$û´üŠý×ÿ1 áæDQK­µÊÿÌþ€ýÌýü©ü×ývþyÿ²=ÁE´/t © y ñ ì ~ a 뼈J9cÖ÷ˆâö!쉈P þéý"û(ù`ø ÷@öö!ööp÷ ÷´øUùù²ú úúGú+úú ùÎùLøs÷ü÷@ö ö4õÕõ¸ö9÷[ø2ù:ú—ûîüðý`þþ2ýþýÑýünûëû€ûûzü<üóþÿK³ ^e!ˆ!˜Â¡L1 ÿ:þžþžþÄþäÿ˜@Í<¿ý®–ÿ<þ„ýÇüâüÓü€ü üVü`üküÂý ýcýðþYþºÿ&ÿjÿUþõþEýü´û­úýúTú%úKú¢ûzüJýOþãGnZÄæÁ÷tÿaþ¢ýÁýýüÖüáýSþ‰ÿÑ#& Äò s D   !ÞñHmr¶²_ÎOÑŠ¶/@ð_U.{ÿ¢þ(üzúÂù´ø¿ø÷æ÷±÷¡÷·øø€ùùŸú1ú¢û ûQûTû ú‰úù,øP÷‡öñö³öEöIö³÷<øeùŸú±ûüýýƒýýpýMü¾üLû­û…ûBúÜû&ûZûÏü²ýèÿ(Ä%D¸¨ž¬‰Š¡±ëÀÿšÿzþüþqþöÿÿÿŠÿö¯Lt(!}ÿ¼ÿAþ¹þeý•ýüsûÛû‹ûJûoûkü+üœüâý„þ$þ¨þºþõþ«þFýsüûÔúÖúùƒù'ùIú ûü ýþÿ'ÿüÉ{÷Ê^©ÿšþtý…üªûõü üBüÏýëþ÷O¢“¨]  FÌG•óøðHÒ~®„u„Çü>îýžXÿ­þtý ûÒúÜù³øØøøˆø„øìù ùJùçú[úðûšü ü"ûÜûTú‹ù™ø—÷Ü÷ööºöà÷uøøéúúàûªüeü´ýýKýüÖüLû£úÜúMúùÝúaú÷ûÃý þ—Hð˜žd<yWdÿØÿþ}þFþ×þìþäÿhÿÿ¾5VGst0ÿíÿuþ“ýúý¤üÑüBûåûLûúâûû‹ûþü²ýšþ^þÉÿ&þ¹þýŽüfûËûDúIú ù¦ù6ùŽù’ùýû&üUýdþ¢ÿÓݹÔö5vÿŠþ‘ý¢üýühü?ülüÂý§þ±ÿÝ'Íœ”„ ! o "~“jâ)uªà¡D_³Ùɶ*e~Aôèÿ‹þUý@ü ûQúzù½ùéúúcû\ûãü“ý'ý}ý`üöýü@ûUúöúùø¸ø‰øDøøÁù`ùÃú—ûÔüûýIýäþ ýÇýZü‚û¾û>úÙúuú?úFúúÎû{ü€ý•þÑ'[YœØ¤;Þä¿ÿÿJÿÿÿBÿ€ÿ|ÿ­ÿätgg=ÿþÿhþfýƒüˆû®û@ú¿úãûûËüü˜ý3ýnýìþNþ€þþ ý°ý üNûoú…ù–ùEù7ùùDùàú¼ûÑý þ5ÿ0,î`*ÿºÿ^þÎýÚýü–û½ûsû‹ü!ýiþŽs‡è-jF³™T r÷Kóί·A¾äxçh|lŠ!s¨®­N†ÿ+ýÖüŠû”úÓúvú‡úþûJû¯ü1üyüÜýEýZý:ýüÂü%úúú4ùføµø\ø5ø{øáùŒú5úüûÙü`üçüòý:ý/üÎüZû¢ûú~ùÑùIù6ù’úúÈû¹üøþÿ?n„‘È>‘!éJóÜ–ÿÑÿ‰ÿ<ÿÿ ÿÿuÿþŸÖ\ÿŠþ«ýýý üjüûDúôû ûOûUûÈüxü¤ýnþQþþ§þéþ´ýúýsü¨û”ú„ùÞù?ù&ùtùóú‰ûüüÑý®þâÿæ…1Îñè#þÛýÊüÊûûû’ûZûÁü_ý5þx “_m*VsN2¹GGø­ü*Awþ`·cf_èîË®„×ÿRþTý•ü¹üQûÇûåüZü ýý…ýãþƒþ®þýdü×ü2ûvúÉú@ù–ùù\ù^ù–ú6úÁûWü0üëý ýPý{ýAý:ü´üûFú0ù·ù1øÑù?ùÌúiû‹üÑýãþËÿ²}îUáôT¤cöŸ:gÿáÿÿ%þüÿÿoÿ¾ÿªG°`º×,ÿÓÿLþný÷ýYü®ûãû;úÓú­úžú¼ûTüüÍýkþþ€þþýÝý:ü­û´û$ú©ùìùcùAøéø¾ùoùéú³ûÉüØþNÿ<:#š›FñÿëþŽýŽüµûìû”û«ûËüYýkþ€ÿ°â"ا1täñ­œKѧ~j‰ÂP4Ü[à‰­¤èš˜Š3 ŸAÿ¿þ£ýýýý¢ý¨ýºþ\þÅþÒÿ6ÿtÿ6ÿþ“ýÄýütû‹û<ûú©úvújú½úôû\üPý1ýàþoÿþöþþý'ü…ûžúÈúpúCúZú‰ú¹ûYüü¢ý=þ2ÿè~'¨'. €ô¸ ˜p†•ÞÎý<<Q?÷…ÿ÷þ·ýüÌûâûzûƒû_ûžüJühüãýŠýðþ;þ§ÿþÈþ¥þYþ"ý~ü¹üûúJúùªù¢ùÙúfûaüˆý½þ÷y”dË—1jÿßÿþýPý,ý@ýFýžþþýÿ“{š„ŽD?¡yŽç§øÍ–Èk'>åˆ 0 Y § { erKÂW:ÿÈÿ:ÿÿ†ÿfÿÿæÿù ÿ ÿÿkþÇýÔý%ü9û_ûûû?û_üýý©þþõÿDÿþûþfýÁýQüµü:û•ûBúÝú_údúeú•úæûjüýýìÿÊ+pµ¡‰Vs6ªjBÿæÿ\ÿUÿ^ÿtÿ 5¢Ó·=ÿÅÿþý+üUûÈû0úÉúú€ú·úÔû$û@ûÈüüÌýKý…ý²ýóý¯ýYüû¥úøúøÝøHø÷èø(ùúû1ü°þ'þþÿו¥{IÿûÿoþîþýîüÍücü/ûñü9üéýÔþ€ÿ¥yö‘AŠåC0<,Õu”ÉÓÎ+ÀK;œ  + ±Û”¤¢ÃÃç'sÿîÿkÿ<ÿBÿnÿvÿ¾A`-ÿÞÿŠþƒý²üíüû§ûDûû?û_üü£ý%ý°þ!þWþyþpþQþqþ@ýèý=üÏü-û,úvúùáùüú[úÆûFûâüˆý?ýëþ§ÿaÿó‹ ?iq(zÿÜÿ„ÿsÿzÿtÿxÿÇ-u©äÃ@ÿ¼ÿeþ›ýýýaüjûËû\ú÷úˆúFúTútúGú¸û0ûˆüEýý¤ýìþýæý-üRûNú)ù0øo÷ð÷þø`øÃù,ùîú÷üüðþÿÿºaÿ£ÿŽþÙýðýeýüxüNühütüÆýZþ6þçÿ„Gâ:£Ý[“þ™A (’èÝç’vnEázÉáàÔß<P@tÂ5Dâÿ!þfý©ý ü²üRûùûÒûóüü+üüÓýtþþþèÿ(ÿ*þáþ¥ýðý&ü–ûæû`ûú½úMúyúfúPúÒû û§ülýýÍþ{ÿ<~ˆSÿªÿ˜ÿbþÝþ¾ÿÿÿÿTÿ˜ÿâ*dYOÿÃÿKÿ<þfý°ýsü¹ü(û•úùÄùPøáøëù6ù¿úû.üüëýýüüü¼üûFúªù°ø¬ø÷š÷6÷T÷®ø&ø¢ùúëû¼ü²ý¯þ•ÿÿyÿaþßþdýèýjüµüƒüTü%üü-üQü†üóý[ýñþÏÿ׺G{B³\_ˆ—á]¾vÛ­2Ò[œ¶~-|9%(ÑÅ{g¨Í¨‹6ѺJÿvþùþˆýâý6üŠüûÏûÒü üküßýGýìþQþ—ÿÿÿ"ÿþÅþžýçýsüÆüû¨ûútú7úúújúÈûªüEüªýþfþëÿYÿÓSÿéÿYÿþÏþçÿ ÿDÿšÿÜÿäSO adQMiÿ£ÿ2þ+ý*üûúdù×ùŽùUùlù·úIúÔû¢ü[ü¿ý@ý[ý#ü¹ü/û¢úøú ùoøÓ÷ã÷²÷}÷`÷ËøoùˆúnûüÔýƒýÙþ"þŠþ€þ\þþ1ýÞýÉý%üü%ûÒûÁûßüü¾ýYþ2ÿQÿùŸ 67`q%P5FT‘Ýtö0,E%§oJ­ÃDˆŸ”»TQH(~EÉ€â5ÿ›þ×þ2ýzüóü™ü~ü™üü²ý ýCýæþdþÏÿ*ÿBÿ€ÿ”ÿ1ÿþ•ýëýAü¾ü2ûNûú¿ú+úú~úÃû.ü'üüý\þ$þšþßþõþ÷ÿ"ÿÿÿ6ÿ+þèÿ ÿÿ1ÿPÿuÿÞÿë9P~ž×¼5ÿÝÿ"þýüûúaúùŠùdù¨ùùúCú”ûûŠü(ü¬ýý[ýü©ûöûúùøø÷¿÷à÷àøBùù“ú4ûûžüUüðý¼þjþþÈþªþ=ýëý\üÖüsûûûÃûéüüƒý1ýúþ{þÈÿeÿØcÇ:£…v[4㋃˜ž*4"ñãx×T5,ÈHÛ×%õdt,>;,ÞšQ"ÈÿÅÿ2þ¢ýÚý#üÝü™üfüŠüŠüøýGýÒþFþTþµÿÿNÿaÿŠÿ~þëþxýèü×ûÔûJúàútúúfú¸úÛûaûùü|ýýtý®ýúþxþzþ¨þ÷þÉþõÿÿþóþ¸þµþ×þÉÿ<ÿÑž^¾Zÿ¢þäþ ývü”ûÈûúSùÎù_ùdùúúÔûƒüLüÆý-ýiýiý"üªûËûKúàùâù¬ùøXø2ø øYøÇù'ù°ú™ûBü6ý?ý­þþYþ\þý²ýQüæü ü¤üIüAühü_üZü´ýAýÇþ‰ÿ<ÿÃV¿ ázŽÿò+@Ö-•™zHS*ì¤àØ•~PŸÐSìÈA+"Î÷ô¢-4ÿÙÿ6þ“ýþýeüèüülüLüŽüóý1ý®þBþìÿ^ÿuÿ¼ÿÑÿhþõþŽýüµü-ûŠû0ú±ú§úÔúÓû7ûcûˆû×ûüüfü×ýEý½þ þiþKýúýäýÑý™ý•þ þFþˆþîÿ€ÿ°ÿï­ðPTýSÿæþîýÜüÙûÇûúZú ù¿ùìúYú³û"û«üvüÙüÍý?ýgý:üöü¾üBûyúþúJù¶øåøfø_øƒù+ùÞú<úÙûìü€üÌýZýÄþþýôýýý¿ýGýüÈüQü%ü1üüIü³ý@ýÝþ{ÿÿ¿#eÔ–tÿÞÿº=ã¾´{z'³²2Çõð’XeQHꘞ¡MJ6¾SâŒ'{!K{ÿ¼þíþBýýSýüü¼ý ýZþ+þùÿsÿîaOÿÊÿQþ¢þ6ýèý\ý üvû÷û­ûEûLûaûVûÜüVüµý6ýZýýšý°ýÈýýÃýÚýÞý¿ý·ýóýøþfþÛÿ-ÿ TÜ[äÅM…ÿkþQý•üjû³ûÍûiúèû û û.ûcû­ü1üÙýgýšþ þýˆüùü¬üúüúžúù¦ùnù+ùIù…ùÞú'ú³ûyûöü˜ýýžþ=þ^þEþUýôý”ý\üëü¨ü’ü†ü¤ü¾üÙýŽþ þ”ÿ\“ ?'Ö}Q+ÿöÿÃÿâ`Š ÁŸu?ð92HŒBK2Ù¿¼±—©{¥+àºJóN‘ë+!ÿ÷ÿ%þBýÞý½ý¯ý¿þ0þÙÿÿ/ÿ‚ÿö,gƒÿØÿEþ—þýqüøüVûüûáûÙûÔûÈüü(ü[ü¤üºüðýýýýJý3üãüÎüÏü­ütücüÖý:þÿ0ÿŠÖ[A÷Ìÿ þaýÈü¨ûûûzú¯ú_úú úCú û!û§ü*ü’üðüãüØüvûõûÉû$ú¿úuùÂùDøåø³øøøæùeùÙúû û³ü^üÄýýdý°ý”ýŸýtýüƒü%üûÝûóüBü¤üûý}þ6þîÿIÿÿçÿþ:Iÿçÿ›ÿ|ÿ:ÿþóÿdÿݹP/ûðŒ9áSVƒÙ‹Í,õæË¡@!.ˆ•¤·j¾ú ?%(“ÿÇÿþ®þxþ þþ^þqþÔÿJÿÈ5k`šžTÿ×ÿxþëþgþýjýcý'ü¹üRüûûûØüüoüºüÞýFýEý%ý@ü¤ü~üû¹ûÉûØüüQü£ý ýëþ{ÿÿÃ`šä0+ùÊ'ÿAþFýGüZû®û2úÔúÔúÖú¸ûû£û¸ûãüYü·üÖüûü¬ü+ûÜûDú¿úvùºùù[øÑø¥øËùùù€ùÓú™û}ûãüˆüñýCýPý1ý:üßüvüoü\üûéü*üsü’ý+ýÉþjÿ ÿAÿá<A1!'ÿøÿÂÿuÿ_ÿoÿsÿâ{Ê'׌™ <Ë•Ã;ö¯™5cÁæ)LPFH9ýJ¢@mb“ñeÿÞÿjÿÿÿ;ÿlÿÙB¹øÚ¾¾…ys5ÿšþÒþ{ý§üòü´üPü\üdü\üœü­ü÷ýGýýJýüˆü%ûõû÷ûÇû£û®ûìü&ü<ü¨üèý°þÿ<¤ [JüÿÔÿ/þýÝýüAûµû1úÝú¢ú ú×û(ûWû…ûæûåûñü-ûÝûÃûžúøú®ú'ùùø”øxøUø\øfø}ø±ùQú ú~û>ûÒü(üvüŠüJüEü1û«ûÈû§ûŠûáûÒûóüZü¢ýEý³þdÿÿ_ÿòÿþÿ™ÿpÿ6þãþÍþùÿLÿbÿ„ÿ®ÿé"5¯^%õ~ˆâ^U6piP¡Ò÷eyu¿Íȶã…rYpÁ÷Fÿâÿ¿ÿáÿ°ÿ·/skÜ54ì”ÿhþÓþ"ý§ý”ý_ýOýªýý[ý~ý…ýpýtý[ý3ýüëüÔüPû¹ûûYûGûšûÝüUüüý þUþþÿ¼g©!n©WÿÎþóþ*ý®ýüyü/û¯û+û\ûEûû_ûvû”ûÔûüûµûÅûÙû’ûú£úeùyøóøÌø^øø(ø:øføÁù%ùÖúCú©û%û…ûÜü<üsü%üûíûWûû ûUûƒüüüðý†ýÇþNþxþßÿAÿ1ÿxÿvÿPÿnÿnÿIÿ!ÿ ÿ*ÿhÿ£ÿçe ³ZÌjÂUÛíê?S[O_y6šÉp¬©,ü\õ&nö9u&«·Pÿñ1zƒ´(µ¥›týÓ-ÿ©ÿ›þõþ—þdþþý·ýªý¸ýÞþ(ýúýÑý­ýOý:üîüsü6ûûû¯ûZû&û<ûqûÒüUýýâþ„ÿÿ·7¾Ü¼ ÿ¤ÿ&þŠýÚýIüÎü@û«ûû‰û2ûúüûûZû¯ûùü üûªûú÷ú—ùñùùDøÖøpøø÷Þ÷¼ø(ø´ùAùÓúkúÄû.û±ûTû@ûnûLûaûjûfûeûšûÒü&ücü²ýýkýÌþEþ±þûÿ^ÿ’ÿ½ÿ¨ÿnÿ€ÿþãÿ:ÿJÿDÿÔ&jŽßz9¡²49%NÃ>á ¤ Ý æ¬:øSËE…£ÃÂE­YD2 MW^¤¨¾¯d ªÿÎÿ^þÙþÔþxþ"þþþ'ý÷þþýÚýíý„üíüÞü­ü%ûšûPûûûû(ûkûÎüsýý²þ„ÿPÿ˜ÿç11/ÿÞÿÑþüþ@ý³üòü˜ü/û§û_ûnû_û;ûBû›û{ûpû§ûûLûûúvú ùø­ø(÷Þ÷ž÷ƒ÷˜÷¼ø&øiøáùuùÇú+úsútúú¯ú¸úÂûûúÎûûYû1û6ûžüücüÍýYý…ýÚþ<þaþ¥þ´þ®þ“þŠþ‰þ”þtþ­þÍþ”þèÿhÿñ}<ÞÈTÙƒ_ˆŠyœø[¡ƒíhãI˜É§Á‡×ý€`Ñ@Íaˆ™o‘ÁÔî;*!¸i4ÔdÿÍÿÂÿkÿ<ÿVÿþöþÛþìþ³þ£þâþoþ!ý·ý'üûîû«ûVûPûfûŠû«û×üˆüÏý5þþþÜÿd<MFÿ¿ÿnÿ8þŸþý°ýqüýüyûýûÎû¥û…û´û¸ûãü?ü(ü4ü ûÛû®û ú`ù¾ùNøóøzø+øøQø?øEøŸø©øÃù6ù ù–ù°ú@ú#úú[ú#ú%údújúGú}úóû4ûˆûíücü”üÙý<ýiýÎþDþþ£þÂþÍþ®þ?þ=þTþ þLþÇÿ7ÿ÷°P´4{’&m•åN“¨âNt±VÄž'C~^e_×Jƒ¼íV{í®; òBku’©„’k{Qùˆ?ÉJÿñÿÈÿæÿ’ÿþÎþ•þ*ýÊýtüÆü|üûÅû¨û}û­ûõüVüÔýCýÄþGÿÿYÿªÿèÿæÿâÿçÿ¨ÿdþîþsþýAüŸü/ûÈûüûùûÅü<üü–üxü2ûéû«û(ú½ú5ù¢ùƒùø¤øjø÷ñ÷ñø÷ó÷óøKø¾ø÷ùùDùDù?ùkùoù†ù³ùÃùðú0úfúSú‹úÄúôû,û¸üUüçýVýÃþþýðþýæýŸýÌý¯ýÃýæþ(þƒþßÿVÿÌ@²wÈÛ[˜šÝAIrFeós¹_ÏÌñ€º£sõ‰Ï?Н>Όܱ}/ Xy´Z<£p@«W%L,ðί§y*ÿ˜ÿAþèþYþýsüùüRüûÉû™ûÔûÁûöüeüÂý ýcýðþaþ­ÿ!ÿÿÂÿèÿÄÿxÿþ—þý©ý_üŸüKü"ûþü*ü@ü9üü!ü;ûñûÙûoû$úÞúaúùŸù[ù ø·ø\ø$ø"ø,øKøUø\øFøaø£ø’ø¤øíùùVùˆù`ù:ù7ù øóù,ù”ùìú:ú¿ûNû­ûùüüŽüÊýý ý=ý9ý=ýüöýJýŸýÄþþµÿÿDÿÝ+Z¼B¤Åô2wî6Ñ:ižo4Õ^âJ@ìÛÇŠ\2·0wðCh*Æ‘¨±¸ üÖ¼»Áp+@"ÅO6+ ÚÀdÿ‰þ÷þ„ýÞýZý#üÎüdûßûÅû™ûJûiû“üü&ü”ý,ý”þ'þƒþçÿÿkÿlÿ þ¢þKýþý¨ý%ü×ýü”ü!ü ûõüüüüûÓûµûˆûú´úSùÏùYù&ùøÁø©øvø"÷Î÷¸÷³÷Ô÷Þøøˆøoø“ø›ø­ø¹ø¥ø¸øŠø•ø·ø×ø×ù&ù ùøúFúÔûfû¾üüoüƒü°üéýü÷üâüèüÖýýdýãþQþ¯þþÿ/ÿ<ÿ¢p¹4´jŽžš¹êA§<ŒÄ[ÝZÈfp€CnQ„sÐSûjª!šíìÅihe^rh4V*Äsm<ö¾ýR ¸›D“9ÿéÿvÿþ¯þFýyýü×ü~üüKütünüÇýTýîþVþñÿÿLÿsÿ·ÿ¬ÿzÿ²ÿbþãþªþaý·ýqý„ý}ý?ý`ýgý1ýü¹üˆü&ü"ü ûšû`ûúúMùìùù)ø¿ø…ø;øYø>ø;øhø\øøžø„ønøXøhø/ø7ø‚ø7ø(øYø‰øëù ùEùñúvúçû:û—ûÅû´ûÇû¾ûÔü+ü`üšüÍüáý ýý3ýŽýüþ þzÿ&ÿvÿÈWš¾+ v­ÂL’æA˜Ç'ˆÓŸYÉüL¹žjÞ®oÍŠòpü“dã÷æ”·Ì™©[;¨“WWhX™{~„T…T/ÛæGÿùÿuþþ ý¢ýQýü’ü?üLüRüü½ý6ýíþ þnÿÿ%ÿÿBÿ1þ÷þñþ×þ¨þNþWþ-ýÝý—ýTýTý'ý7ýýüÖüœüüDü ûÉûpûú“ú=ùùdù@ø­øOøYø>øø1ø ø>øqøPøøiø ø ÷¡÷K÷€÷•÷ø økøåù@ùeùÈù²ùðúIúzú½û%ûvû^ûÅûñûãûéûûü7üUüÍýýkýèþ?þ‰þºÿ4ÿ_ÿsÿÜŽè4ˆÎãKZ²ëQ*ö— V…ÜÿÜÁ5⎀/属Œ±ŒH .¶TV$+ øñ³½¹ª½êî—ŽP@éM(¼*ÿdþùþJýkýFüâü|üxü‰ýý ývýšýÙþ\þiþ¸þÔÿþóþÒþÜÿþÛþˆþ—þ^þþ ý×ý¥ý‹ý“ý¤ýÝýÒývýýüãüü"ûóûƒúçútùÆùFøìø—øžø‰øÂøòø¹øæøßøzø ø÷ö÷…÷²÷Ô÷àøø(øIø…øføÉùù&ù‰ùçúAúyúöúöû ûúþûûûfû¤û¼üNü¹ü£ýýFýTý½þ"þ›þáÿ2ÿ¼ÿíVјñ÷p³ù—sû¯aª'ìTŒñTG ú„·d.íØ‰CNë®i>PÅ”ˆp1åüÞ²®ÌáǪžRè5ÝTÿuþ·þoýöý"ý:ýüýý-ý=ýPýsý°ýÊýðþFþ…þØþçþèþòþÝþáþ¤þ·þ±þaþTþ1þýóýÇýÍý¼ý½ýúþýèý…ý[üÇüûÁûBúºúGú úúù£ùxùuùSùøåø·øQøcø„øBøDø4øø$ø øøø>ønø³øÙù!ùù©ùÜúú#úAú)újúú­ûû&ûJûtûjû§ûüüü4ü¿ý@ýˆýøþgþîÿ/ÿ„ÿ¢ÿ¬%Ge¨Ý?‹¹ýo÷„Uhþ’0¢Í¯¢Ñ½’¸¸J ™p—"æ­]N?¼¢Žd,ኧ±dV'>cF•ÅÎγ*èNÇQ Yÿ¢ÿþ›þJýÖý—ý¥ý³ý¹ý×þþþVþoþ{þºþ¿þÓÿÿ;ÿ þþþèþzþ@þþþýöþBþþfþÑþîþ…þiýëývýü£üFûëûØûµûZûú£ú&ùÌùù€ù^ùSùVùIù øµø€øUø ø÷Î÷´÷âø.øPøˆøµøÙøÝøÙù"ù9ùEùpùÔùñùùúCúOúSúfúSú=ú`úúæûiû´üüVüký ýý9ýÎþ,þ—þÙÿAÿÿyÿÿˆÿeÿ¿ÿø¥\Ô_øœm×a‚Óö sK +øæ¼Ì’ƒx΂t?òíåçdJó¼ˆ4VuœåÌÕY!ð…0¨ÑT*ÿ¹ÿkÿþ×þµþBþþ þWþYþþÑþöÿAÿlÿÿ´ÿjÿÿþ½þ“þŸþ”þÈþûÿÿ ÿ4ÿ-ÿÿþßþ®þtþƒþýëýÂýü½ükûñû€ûJû4û úæú úˆúdúùóù¬ùpù?øèøÑøýùøñùù"ù9ùù1ùtùJùÆúùùú[ú£ú˜ú˜ú ú£ú“ú~ú¥úÔûû@ûoûƒûYûüü'ütüöý•ýâþ\ÿÿQÿkÿ^ÿ†ÿ­ÿ½ÿÜÿÞÿÜj§ó”²“Aª'¢ál”­èÈøÙàó•VTõ[AËps<ó£K  åSpÈàŠ…?á“Üg÷±çÿ‰ÿþþ{þ‹þYþQþtþõÿÿÿ<ÿUÿQÿÿ þ÷þÓþÎþãþÈþþŠþ¤þžþšþ¿þõþçþëÿ ÿ"þñþÔþ”ýüý´ýyý/üâüü‚ü9üûËû‹û%úèúÒú5ùüúùÜù¼ù¤ùàù¤ù ùù)ùù&ùTùpù–ù£ùÙùÞùÆùîú:ú]úzúuúƒúÔúèú÷úíû ú¨ú½ûû*ûWû§üüRüÖýýpýãþ þ_þ¤þ¸þãÿÿÿÿÿYÿxÿ¨ÿþ9~`!]}Í~öhç>~®á)컹¿¥Š9êü˨dV Ë5ëíj??K…Ñ­Þ ÿìðÛ+ÐL&ÿyþüþ£þ®þjþ6þPþeþŠþ•þ„þ‰þ£þ™þºþÎþkþNþtþ^þþ þþ(þKþ<þÂþçþ¹þÇþ­þjþFþ7ýÂý¨ý¤ýSý'ýüÈü7üûËûû!úãúÜúaú[ú?ú ùèù°ùPùù*ù:ùNøñùù'ùù?ù1ù7ù0ùAùTùùÑùàúú[ú“úiúIú€úGúúIúnú•ú˜ûû+ûKûÎûòüUüëý6ýý®þ þ_þiþpþxþdþ‘þ¿þ¹þþÿaÿÑa ~ jŽhÍ+È*´0Z“x*HðÇà¾ÓâÈííÎ|§1²•ŒŽb.N*ð&ŒãªjYè±47wùÿ†þØþÅþòþîÿþíþóþõþãÿ(þöþçþÅþzþ—þvþ‘þ¨þÁþûÿÿ&ÿ/ÿÿþâÿþäþëÿ þÛþºþþvþ%ýÖý€ýüøüÊüŽü’üNû¯ûsûcúíúƒú€úfúúú1ú úúù“ùtù”ùIùIùNùyùÌùûúúmúú~úÎúÎúÃúÛúÍúÌúÉú¹úÛúàúíûpû™û×üNüƒüØýOýžþ-þƒþšþÁþÄþäÿÿÿZÿ@ÿQÿ·\sÜ6sÞ2‘³eñ™üt­·ÍjsÖåÖðÕ—I ‚Açš’FûˆtZ0Sz¡Þ.‚Ø 0Ъ”Y¼p8¹Q¥:ÿáÿÙÿ¾ÿûÿÓÿ”ÿfÿDÿÿ%ÿ ÿ'ÿYÿLÿlÿpÿÿ'ÿxÿ;ÿÿ~ÿuÿuÿšÿ³ÿ…ÿsÿŸÿ1ÿÿþÈþ§þ¯þtýäýÈý§ý7ü”ü;ûîû’ûû^û!ûúúú²ú“ú ùñúùœùùtù\ùzù®ù ù¬ù·ùØùñú6úpúQúºúÂú}ú—ú¯úúVú[ú˜ú£úÁû%û}ûÒü7ü¾ýýTý€þþ*þ"þ$þoþ¹þ³þûÿPÿ„ÿPÿÅÿîÿï+¢æg—QÌvÇõxw¡Øö~—§±…`[;$í‡0-À`¿Nþë,{¹¶è<uÀ ðò”Ä‚¾g(ù}¤®5ÿíÿòÿ‹ÿyÿtÿJÿ¤ÿ’ÿ_ÿxÿŸÿ6ÿ;ÿ<ÿ&ÿpÿZÿnÿþÿÂÿöÿöÿ”ÿ°ÿÔÿÿ¬ÿÊÿ›ÿ¬ÿuÿ%ÿþzþ4ýÌý“ýGýü¹ü…ü|üûØûûQû5úðúú?ú7úùýùöùçùÈùÂùìúúúúEú[ú˜ú¹úÓúÁú®ú§ú¨ú™únúúÄûûqûÇüü_ü²ü³ýý„ýjý…þþFþþÛÿÿŠÿŸÿoÿoÿ ÿÿkÿîV¢-vßœ OÌ5`êEuâFÁ¥”Ñ­®²sy»Ò¼®$ǂĮY«[‡6 xÓ*¬ñ)! ÈK—_1×oûÂ:ÙK5Iÿ÷ÿ®ÿñÿ·ÿ ÿ¥ÿ@ÿÿ(ÿ1ÿGÿ6ÿkÿµÿÿ‹ÿ™ÿkÿ~ÿŽÿlÿ²ÿ°ÿŸÿÊÿù!-ÿÑÿÿŸÿ…ÿ@þÑþƒþDýîý¹ý`ýýüücü+ûÏû€ûcûUûúú_úúùæù½ùÑùšùÇúú4úúú•ú‹úúkúEú9ú)úú)ú/ú úÎúÛûQûLûyûžûæüü1ü½ý`ý™ý¸þEþ€þpþ£þþTþŠþšþÎÿÿÿ^ÿ¿k¤Ñ=Ñ;ËFm˜^k±ð%6tZ<224Çö犤TÛtÞâí?¾K­¾¦®¶z_m)í±ú£_"ÄfLô§”"ÿ¨ÿ–ÿÿªÿ‚ÿ™ÿŸÿÄÿÑÿ‰ÿªÿ–ÿeÿZÿ¢ÿsÿDÿ˜ÿ¥ÿ£ÿÇÿíÿë 0Oc`/ÿ·ÿyÿAÿþ¹þýöýÖýeýJüÞü¬üüû³û…û5úíúnúùáù–ù²ùÞùÍúúQú5ú[úJúúùüùûúú"úKúTú0ú9úEúCúKú•ú´úÄûûLûkû‰üütüÇüéüÝüñý ý:ý?ý-ýIýý¸ýæýÖýîþ1þUþ§þÝÿ'ÿ©-©'äcÝ9næV||¬×ã*'YÍU‚;ž;æTê³yppsžx™&‘¾Â³ŽkÌn:ó¾«vÙ`ÿÊÿ›ÿ[ÿþ¹þ›þ•þ®þeþVþºþtþþ¢þ`þEþ5þ7þNþZþOþOþˆþ·þ´þŠþÓÿþíÿ6ÿÿ†ÿEÿ ÿVþñþþþ<ýÚý¤ýnýý üáüuü|ü7û³ûKúÃú—ú1ùÖùÍù®ùLùSùŒùVùQù<ù`ùIùEùYù6ù:ù_ùBùAù‚ùJùkùsù;ùJù9ù_ùÓúúúpú¿ûúþûûEûsûîûÝûÉü'üzü\üZü‰üUü_ü˜üéýýCýýÚþ%þPþµÿÿ~3©È4EIˆƒ·9€Çý/Ù“A縃*™]d1%B’ÌüE/[i…hVH00§uYñ¤ŠÝ}0ÿ’ÿ­ÿoÿ8ÿ-ÿ þÎþâÿ0þÒþáþÛþ¥þ­þ‹þ¤þ“þŠþƒþ¢þ£þ¨þéÿ*ÿÿYÿïÿÍÿßÿûÿºÿxÿYÿ þßþ§þšþþ^þ:þý¨ýMýü°ü<û­ûqû&ú¸úÃú­únúdú1ú úùæùŽù}ù¹ù·ùÏú ú-ú ú ú úùìùÓùàùçúú,ú1ú/úWúyú}ú¨û û_ûûñü üüEüPü|üdüküáüµüµý+ý6ý0ý…ý½ýý•ýðþþFÿÿ²ÿï_!‹Ù7AD©æS“ñHàÜÉŽe/G&ìsh6•XEê*EJŠí¶¤ñÁ»¸²Œ¸œ^þ®uE ·W –yMÿèÿñÿÑÿ™ÿxÿ›ÿÜÿ­ÿ\ÿ+ÿ?ÿ0þãþ­þ¿þ¥þšþ•þsþíÿAþùÿfÿÝÿ”ÿ˜ÿéÿ¿ÿÿ~ÿ~ÿTÿÿ˜ÿfþñÿ þ£þWþýÄýcüßü°ü“ü üûûûkû*ûúÎúSú]úGú1ú:ùöúJúTú6úaúTú ú&ú_ú5úZú_ú9ú=ú]úVú#úSúuúŽúÁû1ûpûqûËû½û¼ûèûÙüüPüüÓüÞýýMý<ýý"ý,üöý/ýý˜ýþþfþ£ÿÿoÿÖ …È-T‘!õ1S¢%1AZ+âà€ñçè¥VNQA.í>`Fu}§™Ë­¼{ëТ?<N¡o'æ™Wk9=kAJK%ÿöÿ½ÿ|ÿZþ÷þÓÿþóÿÿBÿjÿ†ÿˆÿoÿ°ÿÇÿÇÿ°ÿ›ÿ†ÿÔ\ÿÝÿÍÿÿ2þÛþõþ•þBþ,ýÝýgý7ýükûñûûûÍû`ûTû ú¸úªú‰ú¨ú”úfúˆú”ú—ú™ú©ú•ú“ú§úWúQú_úúVú®ú½úÝûûúüúþû û0û,û…ûüü ü-üÊü¾ü¬üßüÞüßü­ü³ü–üçýýýCý€ýÌýÒþ-þžÿÿ[ÿº%%²BV`• V‡íhÁ…¦Øë¹ÒÛuö³ˆh@ ?á¼'iÈxˆÍÁÑÒ³­r0ñeòÈn Þ÷"ãÄšG!ÿùÿÃÿÅÿ¾ÿ¥ÿªÿŠÿ ÿ‹ÿ–ÿŽÿ~ÿ¼ÿ­ÿµÿÅ+BKY ÿÎÿëÿÑÿzÿTÿþ±þBþý¹ýqýSýü–üdü ûÁûvû4ûúúúÖú³úÒúÁú¿úÜúäú¨úzúnúVúqú¯ú±úªú±úžú¥úÖúªúúÆúÝúÆúüû>û“ûáûûüuüJütüØüÇüµü¤ü üÊüßü¥üÈüÄüöýý/ýÂýäþþþîÿ4ÿ“ÿë"d™è6ƒ%š¡&Á:V|ÆÑãÿåÄ­T!óõy@?;D“…`xޝËý 5.αN¾Lù¿ÎΪÏŽ³kùă}n7:Fÿäÿ´ÿÌÿÊÿ¹ÿäÿçÿï6?tTQ–vy“ˆMÿøÿöÿ£ÿLÿRÿ:þþþþ-þýý6üéüŽü'ûÝûÑûpû{û{ûLûJû ûúîúÆûúæúÄûûû&û û,û1û.úÝúÙúÝúäû úÑû.û‰û¯üüü1ünüÇüñüíüØüöýüòüîü÷üÔüÞüòýý%ý_ý³ýÞþDþ±þÔþéÿ:ÿ„ÿŸÿÑ*u¤,¿ý…¸ú‘çP\¢óñúÙ¤~5 å¶—jx¢mQ*F•uc²Ìí LŒO˜H¾²€eRc8%âλvyP6ö³èªu\ <P%ÿî l”Ô¨¿ôŠ™üÜžW?[Bÿèÿ ÿ„ÿþ•þýÔýÉý,ü½üÖüÌü€üLü_ûÏûyû¢ûeû&ûeûeû5ûJûfû{ûyûzûƒûoûTû„ûBû û?û$ûû$û€ûzûü üuüü®üÎýýIýFýIý5ý+ýüçýý+ý?ý_ýý¢ýìýìþ;þÁþÄþçÿ'ÿ?ÿ“ÿò3:næ-±Z”Òu±Ç½³­fxOìïËmEëî'%+ŠŸ¾0Fs9Õ믧¹b$Aͼ­ŠAWL/ýÙ¡“Žgøª¨Y_BÿöÿùEÿ÷l˜„ ²¥æðÜþæ¾ãÿùÿóÿ¤ÿJÿ8þüþTþþýÊýMüòü®ü†üNü;ü û£ûÓû¢ûiû¤û”û‹ûÔûÓû¾û¤ûû¸û{û_ûfû%û û4ûjû\û«ûùüüYü™ýü÷ýý*ý/ý<ýiý=ý5ýŽýý ýWý×ý¼ý¼þþ%þ6þkþ¨þ—þíÿ'ÿeÿ¥ÿ”ÿÅÿ÷:¤ e·˜þu²ÖKHsr[pSx˜Œ^íP*HÖÝ îb¼«ÿñøÛðÒ²¸È?cpæ×çÜW¡‡<YáäÔ™Š4ܰ¼˜*"9K%PusBgce™¿Ó¯ê÷óâ䲈• ÿÌÿÙÿpþßþëþŽþ"ýóý­ý=ýüíüuü:ûÓûîûèûžû´û¿û¢û™ûùûóûÓûáû§û:û;û0û%û%ú×û2û.û"û›ûžûªüüNüŸüÃüÌüÑüèýýüÎüºýüÖüòýüëý"ýzý²ý„þ þfþVþpþ¹ÿþüÿ ÿ[ÿ\ÿW°?ë „5*_«ÿE¯Ò¾EÆxxHì˜[5D/" j^F¤¤Ü+L0JÂÃÜ©xKYAIFÃÖ¹±à²Á„e^¯v[5JG ȯֺÇןvu¢º ÷í56¥¸pÿ÷ÿÌÿŸÿþÁþ›þVþý{ý üçüºüFûéûòûùüû³ûÓü'ûîûþü ûËûoû«ûžûúüû!ûú×úìû û6ûVûû´ûâü2üYü\üü¾ü­üºüÊüªü“üØýüÈü×ý1ýWýsýÉþþ,þaþ‰þþWþþÑþìÿ6ÿ¢iÞnН"Ó„A´¶  âöëzKE1Ò”J>V5n™²§ì÷÷øÖøââ¡b",ñøôûåê­€ÞÔƒD<^4(:í¹i¨ƒd“¢utÀöêð%"ÖíçÖ‹/ÿùÿöÿŸÿ4þ¯þfþ(ýÄýSýIýüÓüÂü£ü­ü½ü™ü|ülüfüvüAü üûÏûŠûjûUû>û;û?û2ûUûsû¨ûªüüZüRü¼üßü™ü¼üÄüxünüeücüzü üñý'ýký ý‹ý¥ýÑýÞýÜýÔþþ^þþéÿ%ÿRÿ–eT LŸ?‚É4YŽ´ðòÁ¨ª…訮pP¡~Ih”iZ”ÃÒí)"ãÕãÓs‘x8_•h`¡xZ6ꡉtŠWþ³¤j0=ýÑᯈ¹‹G†¨¥¹ÙÖ´ÉÜíÍö÷ÀÔª˜ÿÌÿˆÿÿkþËþþ;ýãý_ý:ý,ýýýüæüßüãüüü¿ü”üyüŽüFûÛûÈû”û`ûLû&úüûûûcû±ûÂûÜü üeüoüEüBüUüü"üüdüpü¥üðüíýý#ý9ý#ýPýFýcý¯ýÄþþ þfþÈþÄþÙÿQÿQÿhÿ×#6¸d«á^îe y±Ñ·~yOÙÉ﯊i4J?S˜y¹Òó ÿýÑœ•Òȶ¶³­n¡¨@<T1¢œŠeo ôÁ‰›„KG¾“¥¹Žl`sPzy6"#„i_¯ÎÑüKâý¾jÿþÿlÿ6þìþ`þ"ýìþý™ýKývýýý@ý+ý-ý%ýüÝü‰ü‚ü%ûáüûªûBû?ûWûFûeûßûáüü"üü"ü!ü<üü/ü<üUülüüÜü×üüÙüýüöý ý+ýkýŠý­þþþþ+þpþoþ·ÿÿÿ<ÿfÿ|ÿº#kÓ7ÓB¨{)nŸ’¹ãŒžÇªT$ Ò®Á­jƒÅ²·K>+LE,ó"ÌÓÛÒÛŸ¯æÍ¨§•dT9øÆ¼žUH2%Ó£OBQüþÜ꾃ˆ„JB…Ÿ¢©ÂÀ VW =ìÕ ÿÌÿ·ÿ0þ®þtþýÝý¨ýƒý[ý:ý@ýIý1ý ýüîüÂüsüûÉû‰ûaûJû7ûDûZûvûˆûƒûVûGûqûšûÏûíûØûýü"üüüBü£ü\üoüŽü_üÆüèüãü÷ý<ýgýpý€ý²ýÎþ þ þþaþoþ„þ{þ¹þâÿÿkÿÄGy¼€É÷‘ÎZ¯¯èmbeKÁ»x0>_Een§±¥èæÛûÒñ¼zŸŽ¢¢»ƒ™”Zk*$ÞðˆUo2'éÎÁ¿eQ+Í1%âÓ΃ƒ­qT6_ ´ó"nyUgGðí“ÿþÿÿþÎþWþýÒý¸ýÉýÎý¹ý‹ýšýuýüçüšü<ü9üûûËû´û<û4û4ûû(û.ûTûŠû?ûBûjûzûÃûßûáûñûåûþûóü*ü?ü4ü7ü/üfüü¨üÂýý ý-ýšýÌýÌýºýäý÷ýÔýñýöþKþƒþþÑþûÿ[ÿ¤Ÿâ;ª“Ô¸ÈðáÕ³¼²czn>‡jpб¾¸¹j¼Ñ²Ñè·ƒ¿­Ÿ¥·»Ÿ¤}V~'ÛÑÄå¶nBÓµÁÒ§‘f_#îã–O{–Ìܳøñ<\€«ß ã£GvG ÿkÿZÿ7þñþƒþqþ—ýüþ0þ;ý™ýpý1ý#ýü­üfü"ûþûØûÉû­ûVûiû4úÖúôû0û û>ûDû+û`ûZûˆûŸû¨û¿û“ûŸûõûñûëüûìüüTüü©üµý ý+ý ý9ýŸýÌý¢ý¢ýøýæýîþ-þKþPþjþpþšþõÿVÿÔ<ÇiÇ£å<c§“œ§^Oƒ;tce‘œŽ¤¸±Õø¸®Ø{…áÈœÍÇx‘Ÿ”K—³hSF`4Ü}oN’¸YJUʉ:2=ôíðÄꢖ{”êÉ÷-_j!öü‹ø³¤-ÿÓÿ¼ÿkÿTÿ þÓþ¥þ‰þþýøýÊýtýYüóüýüÊülü!üFüû×ûþû¨û…ûŠûUû:ûBûjûnûkû§û¾ûÏüüüûËûÍüü%üBüQüdü“ü¥ü½üãýý_ýmý{ýÊýüþ0þGþþþEþxþ€þkþ½þ×ÿ ÿfÿQ´_»AêuÁÛÝFJHV<'TeCb™À“·Ò‰Œ³£Æ¸žÉÉš­ÐÁͨ·Ç£ž–“¹±Œ[\j!çñÁïïû²tZ*1ÄÂ}H§µO`‘B“%g®æQN0È©‡'Í¥=À†y<ÿÔÿÂÿ|ÿ<ÿ"ÿþŸþzþoþ$þ ý²ýŠýEüùüæüŸüjü+ûáûíûÓûšû¹û¿ûžûÙûìûØûÁû¨û«û¹ûíûËûÛûóûÅûßûåüüPüyü†ü üÌý'ýeýtýªý—ýÉþþþ-þKþFþBþ?þ+þKþjþþÙÿLÿ®"”Ü ÍDNÜëúK‚_kœ§¸ÂÎæãNVûó "EHû[»Éñ¼ö6K*ÒÓÓ­Š©ŸTkƒ>Ä´öبÆüȶª Ô½  E ôFJUбNžX¨ã"ÇE,¹!ÿÜÿˆÿpÿJþÈþtþEþ1ýóý´ýªý=ý"ý ü€ü ü9ûÎû‹ûŸû”û:ûûFû,úîûûqû,úæûû6úíúàûFû$ú÷û2û!û!ûQûZûnû½ûÛûóûþü7ü©üºüÔý ýý"ýYý#ýý ý'ýJý&ýZý~ý¿þ*þ_þ¨ÿ!ÿ¬TÞ^¡çA@{Ž£ÆÜôðN@HdS‘¼«¿ûÖŸ“•mŸž{­¸ÁÕËŽ”Á±Oi—Se‚[?èæÆÈÂÜ%*ñ £pGùØ‘E÷øUw»(V”ž€K7ó¹Š,æ„E&ÿÃÿºÿ[ÿ8ÿ þ›þšþ^þ ýÖýý?üýüÂüŽüûüû®û—û}û_ûpû$ûJû(ûû2û"ûúúûúóú¹ûúýúÝúíúÄúÍúÊúæûû:ûPûpû¥ûèü0üRüJü¢üÈü“üuüÑü´üü³üÎüÜüÃüíýý_ý¸þ(þWþöÿˆÿíY÷ñ<`Š×YoZž©‘²î$KcYmdisYVZmp‚¡r„Ã~iŽpb„xtž^´áËÑËáÄÓÄ„<á€^+ÒêîWkR}Wt]Kp"%½›Tãä¹j"ÿÔÿÅÿ“ÿ?ÿþûþÇþiþý¹ý'ü©üšüü!ûÁû±û‹ûjûLû„û;úÛûûûúâúëúàúÓú×ú®úƒúfú_ú-ú?újú`ú„ú¿ú×ûû*ûVûû§ûÃüü%üJüdü?ü;ü0ü"ûâûýü!ü@ü®ý-ýaýmý°þ,þ•ÿ ÿYÿ’%áaƒ›üí ö7©¤È/FK¯”FjKK”TEˆŠƒ`zF“»Éï¿åζeKJ6¸Ë¹ÌÇëu…&î®aÑÄ„k\„¤ƒ± ?s}yœÐš€<ÜÎYçþþ¼•‹A0ÿöÿlÿþÛþþýñýžýGüèüµü“ü1ü6ûöû€ûPûUûjû@ûNû¢ûûOû.úçúú‰úWú[ú¢úpú<ú5úúMú¢údúˆúÞûFûeû­ü üDüküüü;ûýûÓûÑûæûÅüüQüBü†ü¿ý ý+ýþþjþÜÿTÿÄÿü\¢~¢B2;î?žÜ˻۾öøà,+@4ÜÛÝËîøJ4DŒyrTu8,ÎªŽ‡€WdLR„ŽÎ !öÇ®‚@Á€<\sBY_kŽ"8e¶ž¨s{1ÉÍØ‹6ö·©p1ÿ½ÿŠÿPþýÿþ¤þýÂý•ý3üÊüsüBü%üüûÈûüûóû‰ûsûûeûûû4ú·ú©ú´ú%úúCúùëú#ú=úMú‹úÂûûNûvûÙû£ûßüûÉûìûÓûÔû×ûÔüûâû•ûòüû±üü¨üíýcýôþNþeþèÿ'ÿÿ_ÿÑÿþ„ê(?d«Åâéuw{¤×Ô¡ÐÖ…aZš}šÆ§Îû+?œŽK¤•E/Û“Ÿ€pŸˆœÞTn~{K4¨ª](Ò€Šƒ\d¤Ñ?Áñ¼ŸW0ˆP þ¤¾›DP:LÀ–ÿÂÿxÿþ“þDþý·ý€ýyüüüÖüâüüeütüüFüü2ûüû¥ûŸû`ûûúÎú•újúQúdúvú®úìúàûû*ûûjû¨û´ûòü(üüEü üüû¥ûÁû›ûÙûåûØü2üpü¢ý0ý`ýZýàþ1þ2þŠÿÿnÿŠÿ²%ÿïy¸D[¥òTeYWYn;KŠ(!KP%K‘‡²ÆÐt^EnJØÔÜ@:Np[œªÛ +bs¶“5PxPàÆBȯŠ`ž»³×?Nˆ{”¾íÑÝ<´£³VL<+HQ8Ç»¾ Úâ[ÿæÿ›ÿÿþ¢þaþýÎýtýeý#ý üîüòüÓüÃüŽüIü ûÅû£û>û$ûúÙúvúsútúAúaúJú_úfúuúÌúìû ûhûƒû·ûåûµûÁû“ûûxûJûpû6ûJû¼ûŽû¯ü ûíü*üuüÈý+ý@ýÁþ þ!þfþ´ÿÿ0ÿNÿÿÇÿæk”Ü-_o£'@ ÙÑÇ1-‡Ö±Â5;.4A!êËž‰ž£®’¬Þô>"Ž»ÈõèÕ”bܱ1E ÏÁ•Âéí*‚Üñçרž¡¡]‰ËŠ‚‚d~Nüíè`®<ÿÏÿxÿþŽþ0þý¢ý„ý¤ý{ý†ý~üëü½üÆüƒüQüüû¿ûvûŽû2úÈú€úú#ùÏúúEúúsúñú÷ûû<ûFûLûJûvûˆûLûQûqûKûDûVû%û0û!ûnûÂûÂûÍüüüºýýiý²ýÉýäýþþWþ‘þªÿÿDÿUÿŠÿï=­:Y„»òÎÅÄ®„ƒ¨µ½ä(k½Ãþö+öÞÝÓªYDw}{¶FQ¤¿ŠÁÓ“‚jÓª;(ü®®ôdQm¢ÁÛǾ…—¬¬£ËÔË—x™‘ŠÌ¶Z^LÓzáOÿîÿ®ÿ(ÿ"þÝþšþ‰þýóýÔýuý@ý9ýTüùüÔüðüºüuûüûŽû`û$úàúžúsúfú7úaú¨ú…ú˜úÖú¿úúûqûtû?û^ûŸûoû•û£û<ûúøúðû1û?ûWûû“û¢ûëûñüüjüŽý*ýuýuýýýÈýæþ<þ•þ›þßÿ8ÿŸÿ½ÿÅ"}ª<#KY?-0!Fe\LtáûëY‘±Ð¶’¢¢N]<26-'€„~Æîø;¤¡Š¼¿iA;ÔLÞë äV'sx‡‰²§žw:KkJKš”©ô¾Ó²€^س_ùº‹<ÿÖÿ’ÿNþÜþ³þþZþNýÊýøýàýªýºýaýsý1üüxü@ûÎûUûUûOûúçú¼ú¼ú—ú±ú¿úèû%û:ûNûû¥û—û’ûŽûxû\ûKûaûúþûûûûû,ûjûÏûÒüüJüQüÌüÖýýVýSýƒýýÂþþþ;þ—þ£ÿÿ ÿÍgs–¼¤“³´aƒÄuš¼ "?±¾ñacA-4dRþé8Þ¹üØ&No®çœ±Ÿ˜r1+휄“VèáñÇÎ!?§t{ž~"ùV*W³½¢¤¤ÔçÁ„“§h&é½nÝ}0ÿÔÿDÿÿ þÂþ™þþˆþZþ?ýäý¼ý¸ý¯ýsýEý#ü“üDüûÜûƒûNúìúÊûúÝúªúÖûû û,û.û.û<ûeû,ûûQû!ûúæúèûúàú³úðû"û%ûûOûƒû¨üü1ü\üµü©üvüÇüÏüÑýýzý³ýÄþþfþ¯þ¾ÿGÿ®ÿÂAJedas'?A+Os¤;ƒ¤¥ôâñ"íèþëtͯ¡*nÖ±ü++iz„K*; ØŸŽÙ(Ô&VY¡žRp”„_"HK +d]c‚¶ÛÈÆÖ*,áÛ¨pù·„ÜyOÿµÿuÿþþþãþÒþ¸þþfþVþ,þýçýzýjýYü©üAüküûµû`ûZûLúöúüûúÞû$ûKû"ûGûWû_û>ûNû>û6ûúþû ú´úÛúâú¹úèû2û.ûYû³û¹ûÓû÷üLüIüœü©ü®ü”ü¹ý üýý`ý~ý²ýþþqþÁÿ ÿ¿ÿÓÿü OE5/BF3Ou˜²Ýñgãáë!¾ÉÄŸ£k:Oµ”qÛÔöP±æ!XT*øÖ­UdE1/08WnK@P: 8W4!T*ŽÔ¡½Ì;!©¨ˆñ”L©@@ÿùÿÄÿ“ÿGÿÿRÿ þÎþíþ¹þgþ þýÔýmý*üøüüQü'ûæû®ûUûkûpû5ûLûYûhû€û’û”û{û¹û­ûQûeûoû&úìúüû úöúíû+ûKûfûšûÇûÙüü0ü%ü-üxücüLüü½ü¨üëý ý9ý˜ýèþ?þ„ÿ ÿBÿ›ÿíÿäÿóÿÊÿé@:5@ÿóÿóB…§÷:a›ÁÛ¯Ï÷áÉ䵈“[+M`zµ 8P™ç î*˜¡a:QR"kNHA%BaDHh÷óPè-;k˜¤ˆ D.˜‘;?%åžPÒµyÔ‹Žÿçÿø ÿ£ÿYÿŽÿGþäþõþÉþ%þþý—ýpý'ü‰üTüAüûÛûûÎû¾û´ûËûéûýûËûÜüû¾û®ûßû‹û^ûzû”ûGûûhû_ûcû’û´ûÈûßüüü1üEüûùü*ü%ü(üTü†ü©ü¨üýýnýÃþþ}þþµÿ0ÿ8ÿ|ÿÎÿÔÿÖÿÓÿÈÿºÿ’ÿ­ÿ¿ÿ ÿÏÿóÿùcˆ¢á#g`£§¾¹‘šv7B#§J €Û«ñXRGLaeVhV1R?û!Þ0(D2A'1:'8èöG1G¢ô1YZJn“T!ôx7Äf ÑsVkFÿÔÿÇÿñÿ£ÿAÿEÿþËþžþjýüýtýVýü³üYüBûÒûªûâû•û¹û¾û§û±ûšû¾ûÅû›ûÍûžû\ûUûKû&úýû+û:ûû ûnûZûtû¼û´û¹ûØûÏûÎûíûÝû™ûîüûÛûóüü|ü­üªýýýŸþþ7þ}þ«þçþûÿEÿ†ÿNÿoÿRÿ:ÿ†ÿYÿKÿŸÿ›ÿ²@!sÚá6Qs¥¡ƒq%%ìî÷ ó<TJ£â1‚h;™[Qojþ}1ç12KT“ˆ;[JQ_-(!@žÐí8˜¥ÒÞDZz8,¼a Á'M"ªpsPÿøÿÏÿpÿTÿþËþªþ;ýÔý©ý#ü”üšüü[ü@üüüü!ü üBü9ûþüûûûëû·û³û5û1û@úôû+ûGû?ûeûŽû›ûûûŽû•û’ûˆûû„ûyûŸû³ûyû®û×ûÃûéüjü²ü¨ý=ýŽý¹ýâþ2þ½þÜþ­þ¾þöÿÿEÿ'ÿþüÿÿ"ÿÿ[ÿŠÿ‹ÿÃ&STÞÓÚ0QÈ ŽVIˆ¯7€q›Ñ¿ÔéÒÞÄ·µ¾â¯”ÎßÞÒ÷-îáÑ×­»¾Äéë2H˜ÁØ&;cI^ŸH þ œ*%¥f^Î}k†5F[ÿÞÿÈÿÍÿŠÿ(þíþ•þ\þýÒýcüýüÍüü^ühü€üˆüÎü´üyü’üsüûüüû×û½û¤û¤û¾ûŠûÅû¼û€û®û×ûÑûžûÈü4üüûóûóûåûÈûÁû·û¹û¿ûæüüzüƒüÄüëý=ýnýþþ+þþãþòÿ*ÿ1ÿ;ÿ;ÿ þùÿÿ(ÿ?ÿ\ÿ€ÿ®ÿÂÿßTÊ÷#sq??K#þÇ{²¢q²þø"'M™“ÔâñÜÏüî ìë ìýg[+-èÙç…½Ù—¿”Í Gj”ê"1_—h«@'~B¸vOM,í¯jMlt@ÿøÿöÿÌÿþÒþºþ<ý·ýÑýªý=ýýüëüÄüòüûü˜üŠü°üzülüxü&ûëûîüûþûÑû¾û¨ûÅûÂûÓûþûöüüüüBü ûÇû÷ûëûÑûâû´û´û´û™ûöü üüLüšüëý&ýmý—ýüþ1þLþþçþìþÛþ±þëþÒþ„þÔþ¨þÛþÎþ×ÿ8ÿ6ÿTÿä+-gyŽº­azv#%%ÿèÿþ1– °ÚÞ L! YO*^{inŠqT…ԨĽ”Ñ‘gi:*7*e!Fytâ&‚áçÜôÄÄð£L ‘‘~ð®¿ì­ eISÿÞÿ‹ÿÿþˆþ!ýîý˜ýmýZý6ýý üáü¨üsüzü×üzüTü‚üJüû÷ûëûÑûzûiû‰ûû„ûzû{ûû½ûÒû¸ü ü ûÒûåûãûíûÂû­ûÒû¢ûûªû‰û·üûûü6ü³üòüöýgýÒþþsþ„þ”þ·þÂþºþËþÂþÒþ¿þ½ÿþýÿÿ;ÿ…ÿ®ÿØO¤Çâ ó²¹W“S Q<E%1…²ÖD6FvQYv_Vq›µÜáûüù*(4íÄÔŽ¨“QOd=Y“sëe¨nÐ>HPcþ²h"Ít±DýpøÒ9!ÿÑÿsÿþÁþŸþ2þ ýÄý ý¯ýVýgýký?ýOýýüøü^ütüüJüû÷û×û¨ûƒû‹ûvûtûû¨û¾û³ûÔûÎû´ü ûùûåüûãû™û€ûÜûÃûŽû­û´ûûÈüIüfücüøýGýŠýäþ!þTþgþ«þ¢þ™þºþ«þ“þŠþ×þÔþÙÿ ÿÿ7ÿ´ÿòÿØG˜¢Úìç{l­ujF7M99QY­•¯â üñùÜ4,(AKBy£•¥äÛ½¡‹wD?[=5sEV¸ÊüŠÛ÷/4Ôˆ…T"Ù‹¥ƒYDQü´…M%ÿºÿ£ÿBþÛþÂþzþ1þ ýÜý®ý¯ý…ýTýGý6ýaý9üîü¾üÀüüFü=ûùû·û¾û ûhûpû•û—ûmû¿ûÈûûúü ûöûàûÕûßûÆûÎûðûûtû¥ûˆûxûlû±û¦ûçü]ü…ü×ýýfýˆýßþ.ýøþ8þMþgþlþþ{þ“þPþkþÑþÚþÞÿ ÿŠÿÈÿ¡O|ÒŦ©·L+U"%4RUh²Ú¾°ïà ö3*ñ29X¦ùÐÓ ,³Ã©{a9<:ô  //žÒ'q­ÝðàÅìµ~plîø‰ˆª|bGQáÆiAÿ´ÿ^ÿþÓþ¼þxþ:ýçý•ý¥ý—ý“ýzý›ý–ý*ý üýüÕüµü üeü5üAüûÅû«û‹û û‚ûûÓûÅû³û¿ûØûºûÍûçûÑû¦ûûûQûnûúçû ûAûXûhû€ûœûÔü-ü­üìýý€ý²ýÎýÜýçþýöþþ#þ þ\þ\þMþ¡þÞþçÿÿmÿ¿ÿÅÿÏ4cOcnNYb@$7Eaq©®•é×ÌòÑÌØ ÔÞøCbi²¿¢¾÷ÅÕÊ¢¥ˆX0ãÔÞÙ)8´Øj‚ÜÀ¶À«Ž.2)àÙÞ”eX-/ùÂÄ p!ÿÊÿ“ÿ^ÿþåþ¦þOþþ ýÛý§ýçý¶ýŽý|ý–ý[ý$üöü¥ü³üRü6üPü!ûëû¨û¬û«û£û®ûÅûëü!ûþûëü`ü<ü=üjü ûÍûÒû¯û|ûtûû ûMûCûfûûÊü üCü¢üíý+ýCý˜ý§ý•ý÷þ þ%ýóýêþ)þ þ!þ:þfþ²þËÿÿWÿ„ÿÉÿÎNWe˜ Qm]`]/pŽ”w¶ ,g'*shd[n_¥²®å$Oy–‘†Ï÷äñ׸ŠwLÿìó®½ü-}ªÓí Jc—~kNÒ½­Šp¢núCGþ¾qŽòĺlÿ£ÿ¡ÿyÿPÿ.ÿ:þøþ÷þÚþ’þ{þtþ™þ‡þ\þ&ýùý¶ý˜ýpý9ý<üüü¸üÆü¥üŽü«üâýüýýýYýký8ý3ýýü¦üüüüü&ûèûàü&üLüBüüÓüÏýkýÆý©ýÛþþþþMþ<þ>þkþ\þEþ2þ…þþsþËþõÿ3ÿ|ÿ°ÿÅÿßDSd–S7lgW7\eZs¦ ¹Øœèñâ,õ >..I¡Áµï,16o‰„~sCôÞ†“ˆSzvÛƒ®¯¹Çùööô¯‘—y=V1$ÞÂÄk@ÇuAÿÒÿ–ÿfÿþúþÊþ„þuþoþ}þRþBþýàýÚýÄýzý¦ý}ýüÐüžügü7ü6üü0ü üüSü‚ü¢ütü›ü¸ü°ü‡üŸütüüûáûËûlûŠûsû™û­ûlûÕüü ü.üÆýüÙýýLý ý¶ý–ýÍý·ýžý»ý»ýæþýòþþPþPþþÉþÇÿ3ÿZÿwÿ„ÿ¥ÿÞÿ»ÿ²ÿèÿËÿ¡ÿÈÿ¹ÿ¹ÿÚÿÞ)Q†rvŠc–ŠŒ‚ŒãúÖE²ÔÌî&ßêô¤Ö|4Xh4"D^m±­Ê'`µ¡ž’i]J(2I?ýÖ¼ßãs@E ϨNÿËÿšÿuÿCÿþ‘þ{þ~þ\þ7þþ þþýìý·ýŽýFý?üòü•ü{üüüû¾ûñûÈûâü ûáü8ü üHüyü0ü:ü'üûàûÊûÅû’ûPûû"û'ûûû+û•û¤ûçûöüü–ü™üÏýýý$ýHýDýHý5ýGý[ý`ýiý~ý¯ýùþ;þ4þ…þÚþöþôÿ#ÿ#ÿÿlÿzÿsÿqÿmÿ›ÿvÿ‚ÿÿ‡ÿ¦ÿÇÿâÿÕDiZQDˆ5ÿñ<;,qª´ïøt¤ßÀ¶Ø¼Ë²…dd=ï!/ >›¤ÄÅúx_,MˆX^b -#) ïѼqX;éɱ\ÿºÿ§ÿhÿ ÿ þÎþ“þ¸þˆþ>þHþ@þ ýÁýÙý³ý]ýEüÞüÂü-ü:ü?û²ûÞûÒû«û®ûýûáûñü,ü$üüü9üûýüûÙû˜ûzûHû'û?û4û4û:û[û€ûoûËüCü'üAüüÏüýüÞýýxýAý!ýEý:ý.ý]ýƒývý¤ýÎþCþgþdþþÆþæþôÿÿÿ<ÿ7ÿ!ÿXÿ{ÿtÿÿ˜ÿwÿnÿ­ÿÉÿ«ÿÇÿå -8Y@Tr++807Q‡èÎîQ€‡‹ÉÑôøàÂriWT+ôOO?Ž˜È.fL\ŒR\ˆHZinic…cxnP0ïÚÈÆ©Hÿõÿ©ÿKÿ8ÿ(þñþÎþóþ¾þŽþšþTþ0ýúýÊý›ýeý ýüÓüVüVüAü/ûòûúûéüüQüüüVüiü,üIü6ûùûÃûœûÃû‡û7ûaûNûû1ûû"û§ûÀûÀûøü<ü\ü€üÍüòüñüòüúüúýýýbýuý{ý¯ý¸ýÆþþ9þIþ`þ¬þÒþÓÿÿÿ[ÿ–ÿ‘ÿxÿvÿŒÿ•ÿqÿ|ÿÿŠÿ¥ÿÖ PW[o`N+C'ÿý1:;Hj™°Ln}¨¾½þ ÜâÌ^iP8gOO¡§Á0#`*,;8:lgT€…˜aII9Üšsú”HÿøÿÅÿ‘ÿqÿkÿZÿJÿDþÿþÖþÈþ˜þ¡þeþý–ý€ýFüëüÀülüwübü1üHü>ühüCü&üuüCü0üBü=üü ûùûÎû£ûûRû5û=û'ûûûûKû‡û‡ûËûåûîü%üjüüüÎü”üŒüÌüìüÛüîý*ý?ýGýlý¡ý¢ýÈþ$þDþzþËþ«þÂþñþöÿþÿÿOÿ8ÿÿlÿLÿJÿeÿªÿ·ÿ»ÿù1dJ"-ÿùÿìÿø86—›ÍHw›”€¡†cq:5ý(#ü9‘|‹ÏÕª®Ôî÷ë*   4 FQU„,C)éˆ5¿p?ÿ­ÿÆÿ·ÿ“ÿÿ‰ÿQÿÿ þìþ×þ½þxþý¼ý—ýOý üóü®ü•üzüü‡üYüRüTü^ü\ü•üü_üGüYü+ûÔû·û§û+ûû<úðúÞûû"û?û:û}û½û³ûâûõüüü7ü7üFü³üáüÏüÐüþüóüõý+ý~ýsýlýÍýØþþ‹þ€þ—þ­þ¸þÃþÈþ×þìÿÿÿ$ÿDÿLÿ`ÿ`ÿ–ÿÌÿÙÿó:4Ob! *4ÿâÿÙÿå /5s‚¼ýJ„u¢ r˜ˆ}F9pCJL:=RKrRu›™ÕÛéÆï# Bxah„qŒmC9鯍ƒ æà¤c&ÿñÿñÿ¸ÿ¼ÿÆÿÿLÿ+þúþ‡þ\þ=ýØý˜ýbý-ý üöü¯ünüsühügü~ü‘üµü™üpü‡ü‘üsü5ü ûñû˜û<ûeûKû:ûBû1ûBû1ûlûoûzûûÊûÕûÁü)ü1ücüƒühüWü‘üªü¶üÕüÛüíýýMýjý ý¿þ(þ,þþ„þˆþ¹þ½þ~þ½þÇþÛÿþúÿ#ÿ?ÿÿ5ÿsÿ”ÿ¡ÿò)$) *ÿâÿòÿî ÿùB‰­B:G}~^‹´_gV^2>PV60G[‰‚}£ºÂ¸³¶Ô¹µ¿ê!Y—cpydUj['Óå-íÏiSFadÿüÿÆÿqÿmÿ^ÿþ¥þ¬þcþ/ýÚý{ýkýüöü±ü­üðü±üâýüÈýý)üÞü‹üžü“ü*ü üûþûÍû•û¨ûwûû¦ûyûdû¤ûåûÕûÛüü!ü2ü:ücü]ü|ü¡ü‰ü›üÐüØüÜüßý'ýVýcý«ý»ýÔýêþ+þEþNþ‹þþ€þ“þ‰þŒþ›þÏþòÿÿÿ5ÿuÿxÿ„ÿÕÿëÿì(ÿÔÿôC ÿÝÿÉÿ¨ÿ¿ÿíÿßÿÔÿòJA\‚Ô7ùLVC3üí×Ü"-_Lr˜wf‚s„›x¥ÅÍ¿å%E[TYSF%Õ¤{!øåÊ¡Œc‚oAÿä ÿÿÿcÿþîþªþuþ)ý‰ýfýUý)ý"üóüÿýýýüôüçüûüËü¦üÕü¥üzüCü>üüûÍû¦ûÊû“ûÃû£û†ûÕûÖûÍü ü üü=üüNüyü”ü¨ü²üÄüÈü¥ü¼ýý4ýýJýyý¤ýâþþ.þ3þ?þIþUþwþžþXþ‘þ¾þ©þ®þÀÿÿÿ&ÿYÿgÿ‘ÿúÿùÿÛÿ¿ÿ¢ÿœÿ‚ÿÿ’ÿzÿ‚ÿ»ÿÑÿ¹ÿÍ 1HX’ÈçûÞóóõÅÑ$).''QC'bŠ{†}š’‡ÏÔ¹ÿUi|Œd@? ñÒÁ–jV-îÈytœxp^a6ÿôÿÀÿÿ3þçþÏþ©þ[þýÔý“ý ý[ý_ýyýQýRý=ýý(ýHýýý/üÛüØüŸü“üsüü üûãûãü ûÑûÞûÒüüüülüaütü…üªüŽühüüžüœü¥üâýýý(ýKýký±ýÓýÏýêþþ+þ5þAþEþbþ]þŒþ”þ‚þ þþ¦þåÿ)ÿ=ÿvÿÈÿÒÿÏÿÛÿÿÿÖÿ´ÿôÿÀÿ—ÿÞÿüÿ«ÿsÿ´ÿ«ÿ’ÿ¾ÿÕÿÉÿñPWKˆ·²»õïÄýÄÚÛðê ó1!,ztmaeWi‡d=w©Ê÷05gQ`[=4F8È0$üçÝÉ·ÀÔ¯mpPÿéÿµÿEÿþÿþ‹þ\þ}þ%ýêý÷ýåýqýnýœývý{ý—ýaýSýKý9ý?üÚü¼ü¸ü”üšü`üü=ü"ûÿü ü!üIü2üJüxü_üZüvügübü„üŒü\üŒüµü¡üÇüîýý#ý<ýMýyý¤ýÛþýþþ.þfþNþKþSþ/þGþQþ\þ‡þ¢þÕþåÿÿSÿZÿpÿŠÿËÿÑÿ´ÿÖÿåÿåÿÂÿ¸ÿÁÿ¯ÿ¦ÿ©ÿ’ÿ›ÿ¤ÿ£ÿ¶ÿèÿìÿøHcX‡œ¥ÂåÑÏÜÖá°²åÊê%4P`GI_$ 4%-EYy}žÕùè…k|ˆˆTA4À—œJ*D5#óäçóΆ•@ÿíÿÿ‚ÿ5ÿþÝþ—þmþvþAýëýåýÓýÇý¼ýºýºýnýý¢ýUýfýYýüÿüàü£üzüZüCûñû×üüü1ü1üLü3üücü6ûúüKü‡ü}üaüü¬ügü©üÄü²üðýýQýyý¨ýìýÕýçþýåýÓþþFýéþþgþ>þuþ›þ®þªþ¯þñÿÿ6ÿlÿÿ¢ÿÀÿßÿîÿ»ÿ¶ÿ·ÿ«ÿ—ÿ”ÿÿ ÿ¦ÿtÿ¥ÿ·ÿ¼ÿÌÿÙ8ŽŒ|«~¡‡€„²²¬èþ4=$3(ø0_\…ÂÙÊæ73/zL"<ÕßµnogC6nç"̱£e#ÿÿ|ÿ|ÿ þõþÐþ{þRþýôýâýþýñýËýÙþ ýÜýÀýÌý‘ýoýFýüÒüÁüÄürü‚üoü\üdüCü^üjü*üJü{übü†ü’ü•ü’ü]ünü€ügü¤üËüÓüÔüùý;ýný•ý´ý°ý­ýäþýòþþ%þ þ þþ&þ<þaþTþwþ¸þ°þÕþçÿÿSÿ[ÿŽÿ„ÿnÿ¬ÿšÿ¬ÿ©ÿ¢ÿ¬ÿ|ÿƒÿ„ÿsÿ{ÿgÿNÿsÿ¢ÿžÿÅ 7SEGMymyzvuµÞ¹î Úô#îÞíêåö "Gf—Òòòÿ#'.âÛ³¨š]F?FQL@*@ù²¡²Z%ÿÝÿŽÿ\ÿþÓþ±þ‡þNþ7þCþWþDþ#þþýõþýêý‚ý‰ýŽý>ý ýEýüÄüïüÇüpünüpü…üxüküšü…ü}üŠühüaüZü‚üaü`ü¦ü•üÈüÐüÑüõý/ýbýDýxýÉýÈýáýøýøýìþ þ(ýñþþþþþ7þsþ«þ þ¹ÿþûÿIÿQÿ4ÿmÿvÿ«ÿ¤ÿ§ÿ¤ÿ·ÿ­ÿ³ÿ§ÿwÿ^ÿ_ÿOÿjÿkÿŒÿ¹ÿÌÿæÿâ&T,$>dN=hv‹±ÚÀÎ öûA2òòÐÂÍáù +P‰“Æ 'OW:øåħ”§Æ‹Qvccd5;7þãôÒ a ÿØÿÎÿÿ*þõþòþôþµþ¨þ¤þvþ_þZþeþ-þþ(þýùýöýÖý©ýhý]ý-ýýüÞüÖüÔüÖüÌü¾üÂü»ü¬ü­ü·ü„ü†üüxü²ü³üËüÄü·üìýý-ýý•ý›ýÉþ ýîþþýíþþýñþ þ%þ<þkþ‡þ€þ‰þŠþ•þÕþßþôÿÿEÿiÿ`ÿ¢ÿ¿ÿÓÿÆÿ¡ÿ„ÿeÿpÿ_ÿWÿcÿ}ÿwÿcÿÿ¹ÿ´ÿÆÿÿÿáÿÎ %,<0^SVrާ›·æß"ñ óß»¥µª¶â :kv¼ÚÂøéêÑÍøÎÆÐ²•~cWx™idUìÙ°Œ` ÿüÿàÿžÿYÿþøþÀþ­þ‘þRþ…þþoþþEþ3þýòýóýàýŸýŠý—ýHý1ý8üÿüëýýüÞüäü½üÕüÌüšüÁü²üŒüqü•üxükü®ü–ü°üÑüêýý-ýPý]ýýyý—ýÁýÅý½ýÇþ ýðýÚþþ ýðþþ"þ6þdþ^þhþ§þþÚÿ%ÿ#ÿ,ÿnÿ«ÿuÿ^ÿŽÿ†ÿPÿ;ÿOÿoÿeÿ^ÿrÿtÿ|ÿŠÿ†ÿ¨ÿ–ÿ’ÿÝÿãÿæÿâÿíÿóÿö1cp«µ„žêçõþ⵿Îteˆ…… ¼¿ë"(UJuœ~ÖãÉññ­¦ªº„d’¤©§yK^K5 õ·ž[Iÿðÿÿ¨ÿXÿÿ ÿÿ þÐþºþ¯þ¡þ£þ‚þeþJþ-þýìýÁýÏýÏýýdý€ýZýOý?ý ý(ý üøýýüâüÈü¨ü¤ü}üoüoü}ü¤üŽü®üÉüÍüûüóý+ýWýŠýÙý¯ýµýâýÕý×ýþþýøþþþþþþ8þ+þSþŒþ¹þþ¶ÿ ÿ ÿ6ÿqÿ`ÿBÿMÿiÿQÿ]ÿfÿ_ÿdÿjÿpÿFÿuÿÿfÿÿžÿ¿ÿ¡ÿ„ÿÙÿ¿ÿÐÿîÿ´ÿÌÿãÿâÿ¿ÿã1#Ni}˜©Àµ´·‘nuu|UgqL§¢¨ÌÖï0JVSŒ¥”†…………Œ˜}fL`dVdj[XÚ¿ u'ÿÐÿßÿ¿ÿyÿAÿAÿ,þÌþóþóþªþ·þ¹þgþMþxþ@þýðý¾ýµý£ý„ýNýFýgýYý\ýDýCýýý"ü÷ü·ü°üµü©ü“üüµüšüxü­üÈü½üøýýý.ýlýdýrý»ý¿ý¼ýÌþýßýâþ ýäýÁýâýçþ þýøþ(þYþrþŒþÁþ»þûÿ:ÿÿ@ÿ:ÿÿ7ÿLÿHÿ5ÿ7ÿtÿhÿGÿhÿiÿ[ÿ`ÿ™ÿÿpÿ¢ÿ½ÿ»ÿ±ÿíÿ±ÿÆÿ½ÿ¡ÿÙÿï85gm|Ž™“‹¢š’œrllQHA<gˆ¥­Ë%QXEgg™”h¥°q†¡™­¥°º°lW%åб†s@ÿàÿãÿÄÿÿtÿmÿPþõÿ ÿ&þìþÑþºþŸþ‘þƒþDþþýçýÐýÞýÁý¢ý¨ý–ý²ý•ý^ýeýVý!üøý+ýü¸üÊü¼ü´ü¼ü¥ü™ü¯ü¸üÇüÃüÑýýIý%ý>ý¥ý¤ý ýµýÍýÉý¡ý¯ý¸ýÊýÕýÏýÏýÑýôþ þ!þTþVþþ»þÞþÞþíÿÿþþÿ/ÿwÿ*ÿ7ÿHÿ3ÿ(ÿÿfÿ`ÿ`ÿsÿ^ÿ…ÿ•ÿŸÿ±ÿÿ§ÿ†ÿjÿ~ÿ›ÿ«ÿ¥ÿÕÿîÿÛ;W)P_vikˆ\@_d ÿâE-imˆˆ—½ï$>jmF.D69eJwtSƒ¤mweqT (Ü„gÿîÿÒÿ¾ÿ™ÿŠÿkÿKÿMÿ8þôþ×þØþËþ—þuþ~þ`þþ þþþýêýôýúýàý¼ý{ýŽý~ýNýWý#üýüñýýüíüæüðüÒüŸü»ü¹üºüìýýýýgý‹ýƒýœýÝýÌý¼ýëý¯ý­ýíýãýðýðýÐýüýñþþ>þ<þJþtþ™þ þ·þÍþêÿ ÿÿ þùÿÿ'þ÷þäÿÿ&ÿ5ÿ7ÿaÿrÿnÿƒÿ ÿlÿ]ÿ’ÿ_ÿXÿ„ÿ“ÿxÿžÿÝÿ­ÿÖÿû"5+fcYcYd1ÿöÿý$3ÿúÿçQ3"ƒÅÇìÚæíüþü !#/I_bŒ`YyKGAõРhJN&ÿçÿÒÿðÿÇÿžÿˆÿUÿIÿ%ÿþèþ´þ»þœþ¦þ‘þSþAþIþFþ"þþþþýæýåý¶ý°ýªý–ý}ý6ý=ý üäüÙüùüëüÞüÜüóýýý)ýýý`ýý|ýŸý©ý…ýžý¡ýý¦ýÒýÁýÙýÓý³ýåýÎýÞþ'þþQþvþSþŸþ¹þÁþäþÎþëþâþÝþíþÿÿþûÿÿÿ.ÿCÿVÿvÿ†ÿzÿxÿoÿvÿuÿzÿÿÿ„ÿŽÿ±ÿÆÿÀÿ½ÿö5Bdtr`Y[9>f[ /ÿö7DY_ƒ‘¾ÕèÞ×!ú -))=V?MŠk†‘ŒqlSþìýÖŸ„wacV ÿûÿÃÿ³ÿ˜ÿ]ÿ-ÿÿ#ÿþöþàþÅþ¦þŸþ™þuþsþQþQþcþNþ8þQþýûýýýèýÓýªýŠýýsý>ý2ý)ý!ý6ý9ý=ý/ýQý‡ý¼ý´ýšýÏýìýÈýÜýäýÎýÆýäýòýÙý÷ýùþþ þþ5þ5þiþ‚þ“þšþÅþÇþÃþÜþñþùþèþôÿÿÿ$ÿ(ÿ*ÿAÿRÿ<ÿAÿÿ’ÿÿaÿhÿ¤ÿ˜ÿwÿ|ÿ‰ÿ›ÿ‘ÿ¤ÿÄÿïÿú-hN9ZhZ`~eea@1& 2 $ ;ds~}¨ºÁçóìà îùü×7"/ANRrpcOlX3Úº³¹Ÿq‡T0Cÿëÿ­ÿ±ÿ«ÿXÿ7ÿ=þúþóþóþãþÌþ²þ’þrþmþnþpþiþDþ5þVþþþ-ýèýÒýÉý›ýpýmýaýý3ý\ý&ýý*ý3ý&ýýIýUýKý‘ý”ýžýÁý±ý©ý³ý¥ýµý¬ý¢ý±ý³ýØþýøþ)þ:þþVþƒþTþfþ£þˆþ¡þ²þ¨þÐÿþõþëÿÿÿ6ÿRÿ@ÿ_ÿmÿ]ÿ„ÿrÿoÿ“ÿŽÿ”ÿ€ÿnÿ€ÿœÿ¿ÿéÿÓÿµÿéÿìÿý5UcldŽ€t€ƒjKBEtU.Yitc`¦¬°ºÓêä_eGC&2FFLw† ¥¬¥¥ª£¦„šYL>FAÍκ‘eW^#ÿýÿäÿ®ÿŠÿ{ÿ[ÿSÿ;ÿ2ÿ.þóÿÿ ÿÿ ÿþýþìþüþõþÍþ¡þžþrþBþVþDþ$ýûýçýóýéýçýßý×ýóýèýâþ/þ þþ:þ<þfþQþ@þwþ[þEþhþrþ…þvþŒþ þÃþÚþÏþìÿÿ6ÿIÿFÿBÿkÿ_ÿgÿˆÿxÿ}ÿ„ÿÿœÿžÿÏÿÞ  %*ÿôÿô '..Sd[^xœ„±Ë¿Îϵƾ¨±uŒ{‘q™´‘‡³­Ëí%  !1 ý5."Dd^ky‡~sŒ~S„¢q[ka  &íËß¶›¡d!%ÿßÿ©ÿwÿ{ÿ2ÿÿÿ#þåþÖÿþØþçþçþËþàþÎþ«þ}þ^þ~þoþDþ>þ6ýæýëýõýªý¼ýŽýiýcýxýzýzýý€ý¤ý›ý¬ý³ý ýÅýîýÌý¬ýÚýÚýÑýºýÔýòýÄýüþ4þþ7þcþTþgþþ‹þ–þÄþ¦þÐþÊþ¾þîÿÿÿÿ,ÿ-ÿJÿTÿEÿ<ÿdÿsÿ@ÿvÿzÿ^ÿÿpÿsÿoÿÿŠÿbÿ™ÿºÿŸÿÖÿìÿÏ AK1>/-QJ'N3 /ÿÿÿêFjp¸§¼¾¹›ßÏÙÒáç+þ(5=FT\JdoMhF,(ð×ä³–˜[`RÿäÿÊÿºÿŸÿtÿHÿ=ÿÿ'ÿ.ÿþâþéþëþáþÕþÊþ¿þ«þˆþ˜þ”þþlþ[þ?þ1þ ýÚýÉý¿ý¢ý|ý€ý„ýSý~ý‘ýaý•ý³ý|ýý¼ý¢ý¢ý‘ý°ý°ý°ýÏýºý¿ýÎýÛýúýúþ þ?þBþ$þYþhþPþþ–þŠþ…þŒþ¡þ™þ¿þìþÜþ÷ÿ þõþÿÿÿ'ÿ0ÿ ÿ9ÿ$ÿ ÿTÿ>ÿ5ÿ)ÿ#ÿ1ÿ(ÿ@ÿpÿYÿWÿ|ÿÿ±ÿÍÿÃÿÃÿÞÿóÿô.ÿÿÿûÿëÿÍÿâÿëÿ¸ÿ«ÿÛÿäÿâ )GIHCeshtx°¶™··½º·×èîî þú þÞÞÌ¥°œzqvH-ÿàÿÚÿÙÿšÿ—ÿtÿcÿEÿ<ÿ%ÿþÿþÉþ¥þàþ½þ¸þµþ¯þÑþ”þþ’þoþQþ=þ*þýêýëýÀý°ýÈýýZýQý{ýgýLýyýbý~ý‹ý[ý~ýýyýwýwýýý–ýµýÚýÙý®ýÅþþþ þ7þ=þ(þ3þ+þ5þ_þ_þpþ›þþŸþ¼þÒþåþâþ·þÛÿÿÿÿÿÿ#ÿ&ÿÿ!ÿÿ.ÿÿ ÿAÿJÿEÿNÿvÿ…ÿ…ÿÿœÿ–ÿÍÿõ/C ÿåÿØÿÚÿïÿæÿÍÿÛÿ×ÿÓÿàÿ÷ÿí+(-GE?RRlx”–šžœÌÙÂêúÕý òÏøÿÝíÿÝÈÁŒŽXW0ÿîÿôÿìÿ½ÿ”ÿ‚ÿoÿ@ÿ4ÿÿ ÿ ÿþðþÙþüþõþÏþ¿þÀþ¹þ£þŸþfþ/þ;þýéýìýÒýºý½ý¯ý¹ý‡ý|ý¥ý•ý€ý™ý›ý“ýŸýŸý‘ýˆý¤ý½ý¶ý–ýÊý¹ýÌþýìþþ-þþ,þþEþ_þEþ]þoþzþdþ…þþ‡þËþØþ¦þÞÿþÝþáþ÷ÿÿ&ÿ ÿÿÿ ÿÿ5ÿ+ÿ)ÿ1ÿ ÿ0ÿ)ÿ;ÿ9ÿLÿUÿOÿqÿvÿªÿÕÿ×ÿìÿåÿçÿ×ÿ÷ÿõÿ×ÿâÿçÿÈÿ™ÿ®ÿ¸ÿ¸ÿÉÿÁÿåÿòÿÝÿâÿëÿâÿì %D`9-DQosVrv†•¡›¦»Ÿ¦¶¯ÕµŠÅ¯¨““iOZ@ ÿûÿÆÿ¤ÿ±ÿ–ÿaÿ`ÿ^ÿ#þêÿÿÿÿþïþÙþùþèþÓþÆþ¸þ©þ}þnþsþ^þþþ ýÚýÔý½ý³ýÓýÊý¤ý²ý¶ý¬ýýýý’ý—ýý«ý¦ýÌýØýÉýèýîýâýñþþ8þDþ6þ-þPþqþnþ‚þ†þ™þ£þ¦þ¾þ¼þ¾þÇþêþ÷þõÿ(ÿþþÿÿ$ÿ-ÿ<ÿFÿ(ÿ ÿGÿ#ÿFÿ<ÿÿLÿ<ÿ@ÿUÿHÿ?ÿRÿ„ÿÿ’ÿ§ÿÙÿòÿæÿúÿñÿ÷ÿûÿØÿß ÿøÿöÿìÿØÿèÿºÿÖÿøÿî  6:9T[RRkŽ¢šv‡¥¡¨¦²ÏÓÞäıÊÊìýֻê©¢™–^EÿøÿÚÿÇÿ®ÿ¾ÿ‹ÿjÿQÿKÿEÿ1ÿ2ÿ5ÿ%þþþõÿþéþÜþÐþ¢þ›þ‚þ`þMþ7þRþýðþ ýÐýïýõý»ý¸ýÀý“ý¢ýÅýÀý³ý¶ýÀýÅýÉý¾ýÁýÚýàýÝýéþþþþ%þþUþMþBþ_þcþdþyþŸþ”þ¢þÇþÌþ¯þÍþðþäþßþøÿþôÿÿ ÿ ÿ-ÿÿ(ÿÿÿ$ÿ1þ÷ÿÿCÿÿÿ?ÿ5ÿPÿvÿtÿ¡ÿ¬ÿ§ÿ®ÿ¸ÿæÿÙÿÇÿëÿïÿÍÿÉÿõÿ×ÿÇÿÜÿ¸ÿ©ÿ×ÿÓÿûÿãÿ¼ÿôÿÚÿïÿî *=.D]:d„ado©­›”Š´¿«§¹Ûƨ¬ªŸ¨€Œ™k_S: ÿÜÿ¹ÿªÿ®ÿ†ÿ[ÿQÿ;ÿ<ÿRÿ-ÿÿ0ÿ$ÿÿÿþçþÓþåþÍþ—þyþvþHþQþ\þþþýõýßýµýÄýÜýÉý­ýËýÈýÁý¸ý®ý¯ý¦ýºýÈýÀýìþýêþþþþþþþþ>þ;þaþ…þ~þyþŠþþ•þ¹þÈþÅþÄþçþêþêÿÿ ÿ&ÿ/ÿÿ/ÿ7ÿ3ÿBÿJÿ$ÿÿ<ÿ3ÿÿ-ÿ$ÿ8ÿcÿDÿcÿƒÿ›ÿ·ÿªÿÆÿÔÿ¹ÿ×ÿÿÿûÿýÿðÿôÿèÿÕÿãÿéÿÎÿØÿâÿÂÿãÿíÿàÿÝÿøÿâÿøÿýÿí(.<;[`]JQ}ldЗІ¯™ŠÉµµ¬¯³²Ó²¢¹¹z‡x}MB$ÿøÿôÿÆÿ´ÿ¢ÿœÿ“ÿ†ÿsÿiÿjÿsÿ‰ÿYÿ.ÿ;ÿ%ÿþñÿþâþÕþäþ¾þ“þ‰þxþ@þ&þ(þ!þþ.þ ýèýðýúýîý³ýÉýÆýÑýâýÍýåýëýïýîþþþ þ þþ3þ#þ%þMþHþBþAþ|þƒþ^þ’þ—þšþœþþÁþ¿þßþêþÄÿÿÿÿ*ÿ1ÿBÿ'ÿ>ÿBÿÿ?ÿIÿ*ÿBÿPÿ7ÿ0ÿAÿKÿMÿCÿmÿÿ‚ÿ‡ÿ´ÿÍÿÍÿøÿÚÿòÿóÿäÿýÿõÿßÿàÿ÷ÿÑÿÐÿòÿçÿòÿìÿø >#(D>XNcgm°ƒw–¦¥‰«§®Ç·°ÏÎØã»ÀÃÁï—oI-.ÿýÿÙÿñÿÐÿÁÿªÿµÿµÿ£ÿ¦ÿtÿ^ÿsÿsÿAÿSÿHÿHÿ9ÿÿ,ÿþÜþáþ·þ„þ¡þŽþ~þþDþ<þ%þþ#þýðþýõýÊþýêýÝýþýñþþýïþþþ,þ%þþ1þKþ[þHþ^þvþ~þxþ†þŠþ€þÃþÉþ¥þ¾þÅþÌþ×ÿÿ8ÿ!ÿ!ÿ9ÿCÿCÿSÿMÿ%ÿ-ÿGÿEÿ!ÿ2ÿ@ÿÿ)ÿPÿEÿFÿaÿgÿqÿ™ÿ¦ÿ¯ÿ«ÿµÿáÿËÿÍÿñÿéÿüÿçÿñÿùÿäÿèÿêÿèÿûÿßÿï!#"1=49Qzclw|˜‰˜¢¨¥Ò¨ÄßÁÅζÓÙÄ»¯“ŽVPB<<ÿüÿëÿÚÿ·ÿµÿ¨ÿ“ÿ±ÿ‚ÿkÿ€ÿ_ÿlÿnÿIÿGÿ3ÿÿþõþÝþÒþìþØþ¶þšþ¢þ—þrþYþ^þHþ2þ@þþþ/þþþþþ!þýÿþ"þþþGþFþ=þKþeþdþ`þþ“þ„þŒþvþpþþ”þ€þ†þ¦þ°þºþÝþÒþÍþíþüÿÿÿÿ(ÿÿ,ÿ7ÿ$ÿ ÿÿ ÿ!ÿ2ÿ/ÿ$ÿ!ÿ)ÿÿ4ÿ_ÿSÿZÿ}ÿ‹ÿ€ÿ™ÿ©ÿ¤ÿªÿÒÿßÿçÿçÿâÿôÿÌÿÖÿîÿÚÿÝÿàÿåÿãÿñ ÿêÿö"ÿûÿèÿù$ 4/DFOehQL•‹wš–°¾§‹‘±°½èÉÃÙì÷ѵÀ²¥Å“bp4/*ÿöÿßÿâÿÒÿ®ÿ¬ÿ¿ÿ±ÿ˜ÿ‘ÿ‘ÿ…ÿtÿoÿ^ÿKÿTÿTÿ/ÿÿÿþôþâþÚþ¾þ§þ¦þxþeþqþcþ=þ>þBþEþ4þ?þDþþ'þ8þþþ-þþþ@þiþKþTþyþjþgþbþ™þþuþ“þ—þ‘þ›þŸþ¥þºþÁþÕþÙþèÿÿÿ ÿÿÿÿQÿ;ÿ&ÿHÿ7ÿ7ÿÿ;ÿIÿÿ$ÿÿ4ÿ1ÿ@ÿ`ÿRÿbÿrÿŽÿ“ÿ³ÿ¢ÿžÿÅÿÓÿÎÿËÿÜÿ¾ÿØÿÖÿ¹ÿöÿëÿëÿáÿÄÿê ÿÿÿëÿðÿãÿàÿÿÿäÿó'ÿü&%3O5ERo_]{…ujŽss’¡ µÇ›¬Ð×ɳ¿«Äº—¨•ƒrp^B# ÿó ÿáÿ¿ÿÐÿºÿ¬ÿ­ÿ¯ÿˆÿ{ÿÿOÿ_ÿuÿKÿ6ÿ2ÿ>ÿ#þüÿþûþÇþÂþÍþ‚þþ¹þ‡þpþžþ}þhþcþCþYþUþXþhþiþhþmþyþkþ†þŽþƒþ¦þªþžþ™þžþ¯þºþ¾þÆþ¿þÊþÙþÕþÒþóÿÿÿÿ ÿÿ-ÿ0ÿNÿ=ÿXÿ[ÿSÿNÿ9ÿnÿSÿ>ÿhÿKÿ>ÿbÿ`ÿ]ÿRÿXÿvÿiÿŒÿ¤ÿ¬ÿ¯ÿÉÿÖÿÄÿÊÿÈÿÖÿÕÿÔÿÚÿÖÿæÿ÷ÿùÿñÿØÿìÿ÷ÿÝÿä ÿøÿïÿý ÿ÷*5.K_UcrketŠ~‰–£¨«¬³ÇËÇÌæççðæëÑÍÕÉ­‚€lkW)!ÿöÿÿÿºÿ»ÿÔÿ»ÿ¿ÿ¹ÿœÿ†ÿ‹ÿ†ÿbÿiÿsÿ@ÿ/ÿKÿ3þïÿÿþðþÚþµþÈþ¤þ§þ¬þ–þ†þvþ\þeþþ†þuþzþþwþjþzþþ¡þ þ¶þžþžþ¨þ¬þªþ¶þ¿þ¶þ¹þ¾þÛþ¿þÄþÙþ×þÜÿÿ ÿ ÿ ÿ"ÿ%ÿ%ÿ:ÿ8ÿ3ÿ@ÿMÿ@ÿFÿsÿNÿ%ÿ0ÿ/ÿ5ÿMÿPÿfÿgÿWÿiÿiÿ_ÿÿ}ÿˆÿ~ÿ‹ÿµÿ¤ÿÀÿ±ÿ¦ÿ±ÿ­ÿ­ÿºÿÔÿÁÿºÿÈÿµÿ½ÿÍÿÈÿ·ÿÀÿËÿ¼ÿ¶ÿÆÿñÿ×ÿÍÿõÿü *(%HX^Yx|oƒk‰¤“¬³¨ÑÕ°¿¹¤²£Žkk|V8NN-ÿ÷ÿÜÿÖÿËÿ½ÿÁÿ¯ÿ²ÿªÿ¡ÿÿ—ÿ‚ÿ_ÿKÿWÿYÿ7ÿ3ÿ"þÿÿÿþÜþÍþÌþµþ§þžþŠþ{þ“þŸþþ{þþ{þdþƒþþ‚þˆþ—þ“þ–þšþ—þ¦þ¬þªþ§þ±þ±þ®þ¹þ°þÄþãþÀþÞÿþ÷þúÿ ÿÿÿ0ÿÿ1ÿHÿMÿGÿPÿaÿGÿ@ÿ0ÿ5ÿ=ÿGÿTÿFÿIÿ\ÿwÿWÿTÿsÿyÿ€ÿŽÿ’ÿŽÿ–ÿ–ÿ¢ÿ‹ÿšÿ¾ÿ±ÿžÿµÿÂÿªÿ¸ÿ½ÿ¸ÿ­ÿ³ÿÀÿºÿ›ÿ“ÿ°ÿ¼ÿ½ÿ°ÿ¨ÿÄÿÅÿÇÿÛÿÞÿäÿú ÿþ $+3U^SVHr|}Žƒ’¬¦šœ§ ’¡¤”މ‹t]L77#ÿìÿÏÿèÿàÿÂÿ®ÿ¬ÿ°ÿ£ÿ‰ÿ”ÿÿ‰ÿ_ÿMÿVÿJÿJÿ>ÿÿ,ÿ%þøþíþæþÐþ©þ¥þ°þ—þ…þŠþŠþˆþ‚þoþpþþ•þpþ~þ«þƒþ‡þ þ®þ—þþ¬þ¯þžþ–þŒþ§þ¡þ«þÀþ©þ¾þÂþ°þ¸þâþâþåÿ ÿÿÿÿ5ÿ3ÿ-ÿ$ÿ"ÿ%ÿ0ÿ;ÿ1ÿNÿ=ÿ ÿ?ÿVÿ6ÿ1ÿVÿHÿHÿDÿUÿyÿcÿsÿlÿ†ÿÿ€ÿŒÿtÿÿ¡ÿ™ÿˆÿ®ÿ²ÿ‰ÿ•ÿœÿ‹ÿ‰ÿžÿ•ÿÿ¦ÿªÿ¥ÿÿ£ÿªÿ¡ÿ¬ÿÓÿÈÿÁÿÜÿÔÿÐÿêÿéÿñÿý ")*5<B?[iXˆŽ‘ª‘”¤‘Œ“™l~‘`OL8&& ÿþÿéÿÕÿÅÿÒÿÍÿ·ÿ«ÿÁÿ¼ÿ”ÿŒÿŸÿ†ÿ‡ÿ‚ÿ]ÿbÿ]ÿOÿ@ÿÿ"ÿþúÿþöþÏþÎþÄþ¢þžþ®þ¤þ‡þƒþ—þ”þ‚þ«þ¤þuþ±þ¨þþ£þËþÇþ¢þ¿þÁþÃþ¶þÜþÔþ­þ×þÔþ½þÑþÙþñþùþþÿ%ÿ ÿÿ<ÿ)ÿ.ÿCÿ4ÿHÿIÿ@ÿ:ÿKÿkÿDÿ:ÿEÿRÿKÿNÿbÿfÿ]ÿ[ÿmÿiÿfÿwÿ†ÿwÿƒÿ ÿÿ«ÿ»ÿ¤ÿ ÿ¼ÿ²ÿ ÿ³ÿÇÿ±ÿ¡ÿ·ÿ¬ÿ¨ÿ¬ÿ­ÿ°ÿ¢ÿÀÿÌÿ©ÿ¬ÿÅÿÈÿÍÿÉÿÑÿÍÿÊÿèÿÌÿÕÿüÿôTYCD`a[q{‘Ž„„«±‹y‰‰sWV_I31$ ÿíÿàÿâÿÔÿ¾ÿ¯ÿºÿ©ÿ°ÿ®ÿ§ÿžÿ†ÿ{ÿkÿ‚ÿcÿJÿMÿCÿ.ÿ ÿþÿþöþæþâþ¹þ³þÃþ¯þ­þ°þ­þ’þšþþ–þ’þšþ°þ¥þ¬þ½þ¸þ½þ¸þ¶þËþÎþ³þ¯þÇþ¶þÈþÉþÄþÕþÒþãþðþðþòÿÿÿÿ&ÿ;ÿ0ÿ,ÿGÿHÿ=ÿPÿHÿ@ÿGÿEÿQÿPÿLÿ=ÿ=ÿSÿGÿ=ÿCÿTÿaÿPÿ_ÿPÿsÿ€ÿyÿ¬ÿ‰ÿŸÿ±ÿ£ÿÿ ÿ³ÿ”ÿ©ÿ¦ÿ‡ÿ…ÿ£ÿ­ÿ–ÿªÿ«ÿ¤ÿ·ÿ²ÿžÿŸÿ¶ÿºÿ±ÿÂÿÓÿÉÿÄÿêÿïÿåÿÝÿÞÿéÿø &6F>Uvjl€ƒ‹• £™—“›‰hmvFMTE3&(ÿÿÿåÿçÿêÿÜÿÚÿÕÿÇÿËÿ¯ÿ©ÿ»ÿ£ÿŽÿŽÿ¥ÿÿQÿ\ÿ9ÿ%ÿ4ÿÿÿþôþãþÜþçþÙþ¸þÊþÀþ²þ«þÁþãþ½þÌþÝþËþÓþÒþÄþÊþØþÓþ½þØþêþÞþÛþäþÞþÙþûþ÷þâÿÿ ÿÿ ÿ+ÿ9ÿ!ÿ1ÿFÿ>ÿ9ÿIÿNÿ9ÿ5ÿLÿ`ÿEÿ@ÿ<ÿDÿGÿ:ÿ>ÿNÿCÿFÿMÿGÿPÿ\ÿ_ÿaÿtÿzÿ‹ÿ‘ÿ†ÿšÿ®ÿžÿ•ÿÿ¥ÿ™ÿŠÿ ÿžÿ”ÿšÿ–ÿ°ÿ®ÿªÿµÿ¥ÿ¯ÿ±ÿ¬ÿ¸ÿÍÿÊÿÁÿ»ÿ¼ÿ¿ÿÁÿÄÿÕÿáÿçÿâÿòÿúÿù +$71QgjgWkmi“‰ysm{bGU4&;4% ÿèÿäÿõÿÖÿÏÿÄÿÀÿÏÿÀÿ¶ÿ§ÿ»ÿ»ÿ©ÿ”ÿ‰ÿwÿdÿYÿQÿBÿ,ÿ'ÿ.ÿþ÷ÿþúþØþÄþÜþÌþ¾þÝþÊþ¹þÌþÆþÀþÂþÉþÕþÀþÉþÖþÈþ×þòþÜþÙþéþýþâþÖþùþäþðþþþôþüþÿÿÿ"ÿ-ÿ9ÿ2ÿ8ÿ=ÿBÿ5ÿLÿYÿJÿLÿRÿFÿ?ÿWÿRÿFÿOÿJÿFÿ;ÿDÿQÿOÿZÿ]ÿqÿ‰ÿ‚ÿpÿwÿ{ÿ„ÿ–ÿ‡ÿÿ˜ÿ’ÿ”ÿ—ÿ–ÿ—ÿ¢ÿŸÿŒÿ¢ÿ©ÿ™ÿ™ÿ¯ÿÃÿ«ÿ¸ÿÕÿÁÿÂÿÔÿÇÿ¶ÿËÿÍÿ´ÿÇÿßÿãÿÌÿòÿýÿãÿø >=GMK`zu{x›”§‹vŠ€mc[_6- ÿùÿèÿèÿäÿøÿìÿæÿ×ÿÕÿÕÿËÿÅÿÅÿ«ÿ£ÿ¨ÿ‘ÿ„ÿ„ÿrÿRÿLÿ?ÿ6ÿÿÿþûþùÿþôþåþùþïþÛþíþ÷þæþéÿþðþéþÿþÿþñþûÿþõÿ ÿþûþõÿÿþøÿÿ9ÿ9ÿ%ÿ)ÿ>ÿAÿ2ÿDÿQÿLÿpÿuÿbÿXÿkÿgÿKÿOÿ_ÿ^ÿLÿXÿSÿNÿXÿZÿiÿhÿ\ÿWÿWÿ{ÿ{ÿaÿ|ÿŽÿ~ÿuÿŽÿœÿÿœÿ›ÿÿ’ÿ±ÿ ÿœÿ©ÿ¤ÿ¦ÿšÿ¤ÿµÿÃÿ¶ÿ½ÿÇÿÃÿ½ÿÍÿÎÿÄÿÓÿÃÿËÿäÿáÿÃÿÇÿáÿÕÿêÿöÿð ÿþÿé/:C6GYlaodf~\g‚mfee\E7FNÿýÿ÷ÿøÿîÿíÿöÿßÿàÿâÿÅÿËÿÚÿ´ÿºÿÀÿ¬ÿ°ÿ‘ÿŠÿˆÿiÿqÿkÿDÿ@ÿ5ÿÿÿÿÿþêþýþÿþ×þäþîþéþâþãþìþðÿþöþèÿþùþöþùþôþöÿþüÿÿÿÿ&ÿÿÿ9ÿ;ÿ1ÿ1ÿ<ÿCÿVÿhÿfÿ[ÿ^ÿpÿgÿvÿ}ÿfÿiÿeÿaÿ[ÿ[ÿzÿdÿYÿhÿjÿ\ÿ^ÿ‚ÿ~ÿnÿpÿ‡ÿˆÿ}ÿ˜ÿ‹ÿ‹ÿŸÿ”ÿ‡ÿ}ÿ¦ÿ–ÿ|ÿ ÿ¡ÿŸÿ«ÿ¶ÿ½ÿµÿ´ÿÂÿÆÿ¸ÿ¼ÿ¼ÿ¾ÿÍÿ¾ÿ¶ÿÀÿÇÿÃÿÈÿÑÿÏÿ¼ÿ×ÿâÿÜÿßÿÝÿæÿÛÿòÿøÿùÿö""DBSUEbc_pt|yrƒz[er]RJ8*#5 ÿýÿ÷ÿðÿïÿÓÿÞÿØÿÐÿÒÿàÿÊÿ½ÿ¸ÿ£ÿ—ÿ™ÿÿwÿwÿoÿPÿ7ÿ?ÿ5ÿ ÿÿÿÿþôþòþæÿÿ þòþýÿþþþþÿÿþòÿ ÿþëÿÿ ÿÿÿ ÿÿ"ÿÿ(ÿÿÿ7ÿ7ÿ0ÿKÿLÿPÿMÿ[ÿhÿ]ÿ`ÿhÿ{ÿaÿXÿsÿ`ÿ`ÿlÿhÿUÿPÿVÿbÿfÿQÿNÿrÿƒÿrÿrÿnÿÿˆÿtÿwÿÿƒÿ}ÿÿ’ÿ‹ÿŸÿ—ÿ ÿ¬ÿ’ÿˆÿ—ÿŸÿœÿšÿ£ÿ¢ÿžÿ¢ÿ§ÿ¤ÿ§ÿ ÿ¡ÿµÿ ÿ°ÿ¶ÿ®ÿ»ÿÂÿÄÿÀÿÈÿÈÿÙÿßÿÖÿÊÿßÿýÿêÿö $%8HZ\SXV^drSQ`Ld_21>")ÿìÿïÿñÿùÿäÿßÿÙÿÑÿÒÿÊÿÂÿ¿ÿÅÿ¹ÿ®ÿ¥ÿšÿ•ÿ’ÿ{ÿOÿXÿOÿ5ÿFÿ6ÿ"ÿ$ÿÿÿÿÿÿÿÿÿÿÿÿ ÿÿÿÿ ÿÿÿÿÿ'ÿ-ÿ,ÿ<ÿ@ÿ*ÿ-ÿKÿLÿLÿJÿ`ÿ\ÿRÿkÿyÿoÿyÿvÿpÿvÿ}ÿ„ÿjÿVÿsÿqÿbÿtÿuÿgÿkÿlÿYÿ\ÿ{ÿ~ÿfÿ{ÿ“ÿƒÿ™ÿ‰ÿ„ÿ›ÿ¦ÿ™ÿ“ÿ¥ÿ¥ÿŽÿ™ÿ®ÿ¦ÿ¦ÿ­ÿªÿ¦ÿÀÿ´ÿºÿµÿ²ÿÂÿ±ÿ¥ÿ¨ÿ›ÿŸÿ¸ÿ¿ÿ¯ÿ·ÿ·ÿ²ÿÑÿØÿÉÿ½ÿÔÿÑÿÕÿàÿÚÿÜÿñÿ÷ÿûÿù)386FSnorˆ~~k~‚txprtjQQIIHCF'&$ ÿûÿú ÿûÿóÿÜÿÞÿàÿÏÿ×ÿÅÿ¨ÿ¢ÿ¡ÿ›ÿ„ÿzÿvÿ[ÿ`ÿaÿ]ÿ\ÿIÿ]ÿRÿ?ÿQÿUÿRÿPÿCÿKÿeÿ[ÿ]ÿdÿOÿbÿoÿRÿPÿbÿoÿgÿhÿ{ÿ‚ÿ…ÿ‚ÿÿÿšÿŸÿ¡ÿ¥ÿ­ÿ±ÿ±ÿ´ÿµÿ¤ÿ¢ÿÿ­ÿ¿ÿ«ÿ·ÿ®ÿ¬ÿ­ÿ¡ÿªÿ°ÿ¹ÿ·ÿ¨ÿÃÿÏÿÆÿÊÿÇÿÍÿÑÿáÿÏÿÔÿíÿÜÿÍÿèÿèÿØÿîÿóÿëÿèÿóÿîÿâÿíÿëÿíÿåÿíÿèÿãÿûÿóÿíÿìÿñ ÿëÿý ?1&3HR<Qg`u𢴔˜§¥¥““—›–rlgtz\G;I[,2H-)" ÿòÿÜÿëÿÖÿ±ÿ¹ÿ°ÿÿ¡ÿ ÿ‚ÿŒÿŒÿwÿeÿmÿhÿcÿjÿ]ÿWÿcÿcÿiÿoÿeÿlÿiÿaÿaÿiÿdÿeÿiÿmÿlÿ^ÿgÿlÿwÿtÿrÿ‚ÿƒÿÿÿŸÿ“ÿ…ÿ›ÿ¨ÿ˜ÿ¤ÿžÿžÿ¤ÿ£ÿµÿ¬ÿ¡ÿ¡ÿ¡ÿ•ÿ£ÿ¢ÿ‘ÿœÿ ÿÿœÿ–ÿ©ÿ­ÿ¨ÿ«ÿ§ÿ¥ÿ´ÿ¸ÿÈÿÁÿ¬ÿµÿ­ÿ¿ÿÈÿÂÿÎÿÆÿ´ÿ½ÿÄÿ¯ÿ¾ÿÉÿÁÿÄÿ­ÿ»ÿÃÿ·ÿÃÿ¿ÿ·ÿÓÿÕÿÓÿÆÿÏÿâÿÈÿÏÿÛÿÞÿÜÿîÿàÿÕÿíÿòÿåÿø 116CBI`_]vopsioykblaJQW:.76!ÿúÿýÿðÿûÿçÿÙÿîÿëÿÜÿ×ÿËÿ¶ÿªÿ³ÿ’ÿŒÿŽÿ€ÿzÿpÿzÿ_ÿ`ÿ^ÿPÿcÿWÿQÿ]ÿVÿAÿKÿTÿWÿWÿTÿHÿNÿKÿRÿNÿUÿ]ÿLÿTÿHÿbÿ[ÿdÿtÿ`ÿkÿfÿiÿ}ÿÿÿ|ÿŽÿ–ÿ~ÿ|ÿƒÿƒÿ•ÿÿ‡ÿÿŠÿŠÿ‘ÿœÿ‹ÿ~ÿ˜ÿžÿˆÿˆÿzÿ†ÿ›ÿŽÿ”ÿœÿšÿ’ÿ‘ÿ¥ÿ¦ÿ§ÿ±ÿ½ÿ¸ÿ·ÿ«ÿ£ÿ«ÿ«ÿžÿœÿ¥ÿ¨ÿ¡ÿ¡ÿ­ÿšÿ¢ÿ³ÿ§ÿ›ÿœÿ³ÿ´ÿ©ÿ¾ÿ¸ÿ’ÿ´ÿØÿÑÿÌÿÀÿ¼ÿ¥ÿ¼ÿÎÿ¹ÿÔÿäÿÛÿâÿôÿÿ !2(=GHKeo]adhh`JK\^PU@1/-1  ÿýÿêÿöÿïÿçÿèÿÒÿÏÿÈÿ»ÿ¶ÿ·ÿºÿ°ÿ—ÿÿŠÿ“ÿŒÿyÿ„ÿ…ÿ„ÿ„ÿwÿwÿvÿyÿ}ÿÿ„ÿ}ÿ€ÿyÿkÿxÿwÿlÿ€ÿyÿeÿ…ÿ‘ÿÿ„ÿ—ÿ«ÿ™ÿ‘ÿ›ÿŸÿ“ÿ¤ÿ«ÿ«ÿ°ÿªÿªÿ°ÿ¹ÿ«ÿ¿ÿÃÿºÿÃÿºÿ¾ÿÄÿÁÿÆÿ¼ÿ³ÿ´ÿ·ÿÇÿ¶ÿ¹ÿÅÿ½ÿÇÿÄÿÐÿêÿÖÿÔÿÚÿÛÿÞÿæÿàÿÞÿÜÿÒÿåÿÒÿÒÿêÿÔÿÊÿÕÿÝÿÒÿÐÿÜÿâÿàÿáÿãÿÝÿÜÿñÿúÿÙÿåÿïÿèÿæÿìÿõÿóÿúÿõÿýÿý *AEGZermr†{{y†Š…’™Š‡wm]XcUDG;H2$2,/-, ÿûÿýÿìÿãÿßÿËÿÆÿØÿ¿ÿ¼ÿºÿ®ÿ¯ÿ›ÿ—ÿ•ÿŸÿ›ÿ‡ÿœÿŸÿ ÿžÿšÿ¤ÿžÿÿ–ÿ–ÿ„ÿ’ÿ±ÿ™ÿŠÿ’ÿ¨ÿ¢ÿ¡ÿŸÿ¢ÿŸÿ•ÿµÿÇÿ¿ÿÂÿÉÿÌÿÊÿÂÿÇÿÆÿÈÿÇÿÊÿÌÿÏÿÕÿÖÿÆÿÖÿáÿÇÿÔÿÓÿÁÿÕÿÖÿÔÿØÿÖÿÓÿÎÿÙÿëÿçÿàÿðÿìÿõÿöÿèÿûÿíÿòÿøÿðÿýÿùÿèÿãÿèÿøÿèÿðÿõÿôÿñÿóÿøÿóÿýÿÿÿõÿøÿúÿþÿõÿøÿø-74GOXo\Ws‘Œ€ˆ‚}˜¬”‹Ž„ˆ‡snhXQQOFC58=0-"0<7+ ÿõÿãÿØÿàÿÕÿ¿ÿ½ÿÂÿ¾ÿ©ÿ±ÿ®ÿ­ÿžÿ¡ÿ¤ÿ™ÿ£ÿžÿ®ÿºÿ«ÿ™ÿœÿ–ÿšÿ¤ÿ›ÿ¬ÿ§ÿ˜ÿ§ÿ¬ÿ©ÿ©ÿ§ÿµÿ¸ÿ³ÿ¶ÿ´ÿÊÿÆÿÁÿ¾ÿ¾ÿÑÿÐÿÄÿËÿÒÿÕÿÕÿÐÿÎÿÉÿÉÿÕÿÓÿÐÿàÿÛÿÏÿÇÿÅÿÕÿÌÿÓÿÜÿÑÿàÿÝÿÛÿéÿùÿðÿòÿêÿòÿõÿñÿðÿ×ÿÜÿÞÿÐÿÙÿëÿÞÿÐÿîÿ÷ÿñÿèÿèÿðÿ÷ÿæÿÝÿùÿ÷ÿìÿòÿõÿõÿõÿñÿîÿíÿë ÿûÿú  +A;LNO_nimnr}ƒhy’vtz]bn`YRLCB9KG2<A/3<<*!.ÿìÿáÿÚÿÆÿÚÿÐÿÆÿ¸ÿ³ÿ¯ÿ³ÿµÿŸÿªÿ¶ÿªÿ›ÿ£ÿµÿªÿ¡ÿ¦ÿšÿÿÿœÿ®ÿ¤ÿœÿ¦ÿ§ÿ¯ÿªÿ«ÿ±ÿ¬ÿ®ÿ¶ÿ±ÿ·ÿÍÿÏÿÉÿËÿÝÿáÿÔÿÝÿÐÿÉÿÚÿØÿÐÿÉÿÏÿÀÿÉÿÎÿÉÿÛÿÅÿÆÿÏÿÊÿÑÿßÿÝÿÝÿÙÿÔÿÛÿçÿâÿãÿóÿóÿöÿêÿéÿìÿÞÿÛÿäÿèÿßÿÞÿâÿù ÿõÿþÿöÿÙÿìÿîÿíÿãÿîÿ÷ÿãÿìÿßÿåÿõÿèÿèÿëÿÛÿìÿíÿÝÿôÿñÿçÿý !('0;ORUc_FXbebXibboaJNA;9'1#  ÿüÿõÿöÿñÿæÿæÿßÿÕÿ¼ÿ­ÿ°ÿ¦ÿ¶ÿ ÿ—ÿ¢ÿ”ÿ‘ÿÿŽÿ‰ÿ|ÿ‚ÿÿuÿvÿ€ÿ‰ÿƒÿqÿuÿÿÿzÿqÿtÿxÿxÿsÿxÿÿÿŠÿƒÿzÿÿÿ‹ÿÿÿŸÿ‚ÿÿ›ÿ‰ÿ“ÿÿ™ÿŽÿ‚ÿ–ÿ–ÿŽÿ”ÿÿÿŠÿ’ÿ‡ÿ‰ÿ•ÿƒÿ~ÿÿ”ÿ‡ÿÿœÿÿœÿ©ÿ¶ÿ±ÿ´ÿ¤ÿ¡ÿ”ÿ¡ÿ«ÿ’ÿ›ÿœÿ–ÿŸÿ©ÿ¤ÿŸÿšÿ¯ÿ²ÿªÿ°ÿ©ÿ­ÿ°ÿ´ÿ¯ÿ¸ÿ©ÿªÿ©ÿ¤ÿ¬ÿ™ÿœÿ°ÿªÿ¥ÿªÿ¨ÿ«ÿ²ÿÇÿÏÿÂÿ¾ÿÐÿçÿëÿèÿæÿ÷ #3)@% (&)ÿÿÿôÿúÿÿÿëÿîÿòÿøÿòÿãÿëÿëÿìÿöÿæÿßÿæÿßÿØÿÇÿ¾ÿÊÿºÿ±ÿ·ÿ›ÿ‰ÿŸÿ–ÿ„ÿ‡ÿÿ†ÿÿqÿrÿ}ÿuÿvÿ‚ÿoÿlÿrÿtÿhÿdÿhÿ]ÿ]ÿjÿeÿeÿtÿnÿrÿ|ÿoÿvÿ~ÿÿyÿwÿÿ{ÿyÿ‚ÿŒÿ—ÿÿŒÿ—ÿÿ‘ÿ˜ÿ—ÿ£ÿ™ÿÿ ÿ£ÿ£ÿ—ÿŒÿƒÿ”ÿŸÿ‹ÿ”ÿÿ“ÿšÿ”ÿ¤ÿžÿ¨ÿªÿ¤ÿ¨ÿ§ÿ¬ÿ°ÿ±ÿ¥ÿ¤ÿ£ÿ¨ÿ ÿ ÿ¦ÿÿ£ÿ­ÿ®ÿ¬ÿ¯ÿ¹ÿ¸ÿÅÿ¾ÿ¿ÿÁÿ±ÿ¿ÿ±ÿ°ÿ¿ÿ²ÿ®ÿ¼ÿºÿºÿ¿ÿ³ÿ·ÿ·ÿ¸ÿÀÿÊÿÇÿÌÿ×ÿÐÿÛÿíÿú$/%+2$+11,<'ÿùÿú ÿôÿþÿûÿúÿûÿñÿèÿêÿåÿàÿ×ÿÕÿÓÿ×ÿÆÿ±ÿ­ÿ£ÿ£ÿ¢ÿ™ÿšÿŠÿ„ÿˆÿŒÿ‰ÿ}ÿ„ÿzÿxÿxÿoÿoÿbÿfÿxÿkÿlÿoÿcÿoÿoÿvÿ|ÿ{ÿwÿ|ÿ‰ÿxÿvÿˆÿ~ÿ†ÿ‹ÿ‚ÿƒÿ}ÿ‹ÿÿÿÿ’ÿšÿªÿ£ÿ¤ÿ¦ÿœÿ˜ÿ™ÿ¡ÿ˜ÿŽÿ£ÿÿ‰ÿÿœÿÿœÿ¦ÿ¥ÿ¨ÿ±ÿ±ÿ©ÿ±ÿ¹ÿ±ÿ¥ÿ¹ÿ¨ÿ«ÿ³ÿ§ÿ®ÿªÿ ÿ¤ÿ­ÿ®ÿ§ÿ¹ÿ·ÿ«ÿ»ÿºÿÂÿÇÿ½ÿºÿ¿ÿ¿ÿ½ÿ½ÿÂÿ½ÿ»ÿ¿ÿÆÿºÿ¹ÿÅÿ¼ÿ¿ÿÃÿÌÿÕÿÔÿÜÿáÿÝÿßÿéÿéÿøÿñÿþ)40'/65?<@C655#  ÿûÿûÿÿÿõÿúÿéÿïÿïÿ×ÿÊÿÔÿÎÿ¶ÿ½ÿºÿµÿ¼ÿ­ÿ¥ÿ¢ÿ£ÿ ÿ˜ÿšÿ•ÿšÿŽÿÿ‘ÿ’ÿ€ÿŒÿ‘ÿ…ÿ„ÿ}ÿŽÿ—ÿƒÿƒÿ‹ÿŒÿ‘ÿ—ÿŽÿ›ÿ•ÿ„ÿ›ÿžÿ ÿ©ÿÿ™ÿÿ¤ÿªÿ«ÿ¯ÿ»ÿ·ÿ¸ÿ®ÿ¢ÿ±ÿ»ÿ´ÿ¬ÿ°ÿ©ÿ¬ÿ®ÿªÿ­ÿ³ÿ®ÿ¿ÿÀÿÀÿ»ÿÀÿËÿ¼ÿÈÿÇÿÊÿÌÿÀÿ¹ÿÄÿÅÿ¿ÿ¹ÿ¹ÿ»ÿÂÿÀÿÃÿÎÿÎÿÏÿÁÿÐÿÕÿÕÿÑÿÊÿÎÿ×ÿßÿ×ÿÍÿÉÿÐÿÕÿÒÿÑÿÔÿÓÿÙÿÛÿÕÿÚÿéÿêÿäÿæÿøÿøÿòÿúÿþ '4-/ABHLHB?Q;)4)%,/#  ÿüÿùÿÿÿôÿöÿïÿèÿÜÿÞÿâÿÔÿÃÿÂÿÁÿ½ÿ¼ÿ¸ÿ°ÿ°ÿ©ÿ¡ÿ¡ÿ¦ÿ¨ÿ•ÿ‘ÿ—ÿ–ÿ–ÿ’ÿ“ÿÿ†ÿŽÿ”ÿ“ÿ“ÿÿÿ–ÿ•ÿ‰ÿ“ÿœÿœÿšÿ‘ÿ”ÿ¤ÿ©ÿ­ÿ©ÿ°ÿ²ÿ¹ÿ¹ÿ·ÿÀÿ½ÿÃÿÁÿ¸ÿ­ÿ´ÿ¼ÿ°ÿµÿÁÿ¶ÿ¦ÿ¸ÿÆÿ´ÿµÿÑÿÏÿÃÿÍÿÚÿÈÿÏÿÜÿÍÿÏÿØÿÖÿÅÿÊÿÎÿÑÿ×ÿÑÿÓÿÒÿÍÿÔÿÕÿ×ÿÞÿÚÿ×ÿÚÿÝÿàÿÔÿÜÿÞÿÒÿÞÿÝÿ×ÿÓÿÎÿàÿÙÿÞÿåÿäÿéÿåÿáÿèÿôÿùÿú !)/,@E<PSQZ^SUI:9:6,-+*!#*&)!"& ÿÿÿüÿüÿïÿèÿîÿæÿßÿÑÿÐÿËÿÃÿÉÿÆÿÁÿºÿ¸ÿ­ÿ´ÿ®ÿ³ÿ£ÿ”ÿ©ÿÿ‹ÿ’ÿ¥ÿ™ÿÿ¯ÿœÿ™ÿ¤ÿ¦ÿ—ÿ˜ÿ¢ÿ•ÿ ÿ¨ÿ›ÿÿ©ÿ«ÿ«ÿ«ÿªÿ¿ÿ¾ÿµÿ¹ÿ»ÿÂÿ½ÿ¾ÿ»ÿÂÿÁÿ²ÿ±ÿ¿ÿºÿ©ÿ»ÿ»ÿ¯ÿ¸ÿÅÿÆÿÆÿÒÿËÿÌÿâÿÌÿÐÿäÿÜÿ×ÿÕÿÎÿÖÿÕÿÓÿäÿÛÿÐÿÔÿÖÿÛÿÛÿàÿæÿßÿéÿÝÿÚÿæÿèÿàÿßÿäÿîÿåÿçÿóÿäÿóÿëÿçÿéÿîÿïÿæÿéÿûÿûÿõÿúÿü .4-5>JCGNNXVPFFLE>AB37>,5*$0*),&,) ÿÿÿóÿèÿäÿæÿâÿÜÿäÿÜÿÕÿÌÿÍÿÉÿ¿ÿ¼ÿ¼ÿ¾ÿ´ÿ³ÿ¼ÿ²ÿ­ÿ®ÿ¬ÿ§ÿ¤ÿ´ÿ®ÿ§ÿ±ÿ­ÿ¤ÿ®ÿ¶ÿ¦ÿ¢ÿ®ÿ­ÿ«ÿ±ÿµÿµÿ½ÿÂÿÃÿÀÿÃÿÏÿÍÿ×ÿËÿ¾ÿÃÿÉÿ¿ÿµÿ»ÿ¾ÿ»ÿ»ÿºÿÉÿÈÿÇÿÊÿÎÿÕÿÔÿØÿÛÿçÿàÿÞÿáÿÚÿáÿàÿ×ÿäÿÝÿÕÿéÿäÿâÿîÿâÿèÿãÿìÿíÿäÿñÿõÿöÿøÿñÿñÿñÿðÿòÿéÿëÿñÿõÿöÿöÿõÿ÷ÿûÿøÿöÿüÿøÿü  +0)4?=LOOSQ]PMTCKK@H@=:732448;9/%%0*""  ÿýÿþÿöÿûÿçÿçÿîÿæÿãÿÕÿßÿÛÿÙÿÔÿÁÿÈÿÉÿÂÿÃÿÂÿÃÿ¾ÿÀÿÂÿÂÿ¾ÿ»ÿ»ÿºÿ½ÿÂÿ»ÿ³ÿºÿ¸ÿ¹ÿ¸ÿ»ÿ¸ÿÁÿÐÿÌÿÉÿÉÿÙÿÛÿÒÿ×ÿÔÿÆÿÇÿÏÿÏÿÈÿÎÿÓÿÆÿÆÿÒÿÐÿÏÿÜÿÖÿÐÿÒÿßÿÝÿØÿçÿéÿéÿìÿçÿæÿëÿèÿÝÿâÿçÿäÿÝÿåÿæÿëÿéÿæÿóÿòÿïÿ÷ÿøÿøÿóÿöÿöÿóÿøÿúÿüÿøÿöÿúÿøÿøÿþ!(25:<;FMPWSVRUTORQFCOCBL;>9697=><:4,,,'2$  ÿþÿþÿõÿéÿóÿòÿåÿàÿáÿãÿÑÿÒÿßÿÔÿÔÿÒÿÏÿÔÿÎÿÆÿÅÿÔÿÏÿÄÿÃÿÊÿËÿÈÿÇÿÈÿÈÿÉÿÐÿËÿÊÿÕÿØÿÓÿÖÿßÿÞÿãÿãÿÞÿàÿßÿÛÿÛÿÙÿÕÿÖÿÚÿÐÿÐÿÖÿÔÿßÿÜÿÐÿÝÿâÿâÿêÿåÿÙÿáÿéÿåÿäÿåÿæÿìÿòÿèÿëÿôÿôÿôÿ÷ÿñÿîÿøÿõÿöÿþÿüÿúÿ÷ÿýÿúÿôÿýÿùÿÿÿú    *3.3;CKRRJMRSPLNLGHL=AK=>H?@@=@=972)30 +" ÿùÿðÿöÿñÿðÿìÿÞÿàÿãÿãÿØÿÙÿÝÿÍÿÓÿÜÿÙÿÖÿÜÿÓÿÎÿËÿÇÿÑÿÊÿÇÿÏÿÊÿÄÿÏÿÐÿÐÿÓÿÜÿØÿÓÿäÿÛÿÜÿéÿåÿßÿàÿßÿÖÿÓÿÜÿÜÿÐÿÏÿÔÿÏÿÕÿÜÿØÿÚÿÕÿØÿÞÿàÿÞÿàÿáÿâÿæÿæÿÝÿæÿòÿèÿåÿìÿäÿíÿìÿåÿìÿéÿíÿñÿòÿôÿõÿöÿõÿóÿïÿòÿñÿðÿõÿõÿöÿòÿøÿüÿùÿþÿþ     !!(39<LRIJLORSIFLKMIFKLHNE@JBFI>?8>7191,1*,' ÿõÿöÿ÷ÿëÿæÿêÿèÿêÿêÿíÿèÿâÿãÿäÿâÿáÿÞÿÜÿÚÿÑÿ×ÿÚÿÒÿÒÿÝÿßÿØÿàÿâÿâÿèÿëÿéÿèÿñÿ÷ÿíÿæÿêÿêÿìÿðÿãÿÚÿáÿéÿàÿÞÿçÿåÿÜÿÛÿäÿäÿáÿåÿéÿïÿêÿçÿðÿïÿáÿèÿðÿêÿîÿìÿïÿóÿõÿðÿðÿðÿ÷ÿüÿúÿùÿøÿøÿúÿøÿÿÿûÿøÿúÿ÷ÿþÿúÿû  $.//<BIIJMKMMHJMGLPKIGFIJI?AD?EC?9933950--&#  ÿþÿ÷ÿöÿôÿòÿðÿíÿíÿîÿèÿçÿìÿäÿèÿçÿæÿìÿßÿåÿäÿãÿâÿÕÿÜÿÛÿÜÿáÿäÿáÿáÿíÿîÿêÿçÿðÿòÿïÿìÿñÿðÿèÿìÿáÿàÿçÿæÿãÿáÿçÿäÿãÿäÿæÿãÿäÿðÿëÿäÿæÿìÿïÿêÿæÿåÿãÿåÿãÿæÿçÿéÿéÿîÿñÿïÿïÿîÿòÿôÿóÿïÿòÿîÿîÿóÿïÿíÿõÿñÿîÿïÿóÿõÿ÷ÿüÿûÿüÿøÿÿ  %&,04=<>CCCA>?<BA;<@=A=;C<;46;56730',-&,( %   ÿõÿúÿöÿõÿñÿõÿòÿíÿëÿñÿ÷ÿëÿçÿóÿðÿáÿãÿçÿäÿáÿãÿÛÿâÿæÿÝÿçÿëÿäÿéÿöÿòÿîÿóÿîÿïÿðÿöÿ÷ÿðÿðÿðÿêÿæÿçÿìÿæÿàÿðÿîÿåÿïÿñÿìÿïÿîÿíÿòÿðÿñÿíÿæÿíÿíÿéÿíÿìÿêÿïÿïÿïÿíÿñÿöÿñÿóÿøÿóÿðÿùÿóÿïÿõÿóÿðÿñÿëÿðÿöÿóÿñÿóÿþÿþÿþ ÿÿ  #,%.4.1:946:95@?><29>5:??>666274,,.(')!&! ÿÿÿùÿôÿûÿïÿîÿöÿùÿ÷ÿòÿñÿïÿîÿðÿêÿçÿéÿêÿáÿÞÿäÿáÿÜÿÞÿçÿåÿãÿèÿèÿëÿïÿîÿïÿñÿôÿõÿíÿëÿðÿîÿæÿæÿéÿéÿçÿéÿðÿíÿëÿéÿåÿëÿìÿçÿîÿðÿðÿëÿæÿðÿòÿêÿêÿíÿèÿíÿòÿðÿëÿòÿóÿëÿíÿ÷ÿöÿïÿóÿîÿíÿöÿõÿóÿòÿïÿëÿëÿïÿôÿùÿùÿøÿöÿþÿüÿýÿþÿùÿüÿûÿûÿþÿýÿýÿù  #(++,(0).1).,..0)36/002.)-+-+)(#$# &"  ÿþÿûÿüÿýÿýÿøÿùÿûÿýÿùÿöÿõÿøÿðÿìÿèÿåÿéÿçÿçÿèÿêÿéÿçÿéÿìÿíÿíÿðÿôÿîÿóÿøÿóÿôÿøÿõÿòÿñÿñÿíÿêÿëÿìÿñÿóÿðÿñÿëÿðÿîÿíÿöÿôÿðÿíÿíÿîÿíÿíÿõÿòÿïÿõÿñÿðÿïÿôÿ÷ÿóÿôÿôÿøÿùÿüÿøÿñÿøÿôÿíÿñÿ÷ÿîÿìÿöÿóÿõÿùÿýÿûÿøÿÿÿþÿúÿüÿÿÿÿ !%(##))$(+++/1*.4/+-/--0&%1*#'&"" "   ÿýÿüÿýÿùÿùÿúÿôÿùÿ÷ÿñÿñÿëÿîÿìÿæÿíÿïÿéÿêÿñÿðÿíÿôÿøÿïÿöÿúÿóÿöÿõÿúÿõÿïÿ÷ÿñÿðÿõÿðÿîÿõÿõÿõÿöÿðÿñÿóÿóÿôÿñÿðÿñÿóÿïÿðÿ÷ÿðÿìÿóÿðÿîÿóÿöÿôÿ÷ÿúÿöÿõÿøÿ÷ÿòÿöÿòÿôÿøÿôÿôÿïÿòÿüÿôÿôÿûÿûÿûÿþÿýÿÿÿÿÿýÿýÿþÿÿÿüÿÿÿÿ  "# $ "" " %&$&!! " ÿüÿþÿüÿýÿÿÿûÿûÿúÿúÿüÿüÿùÿôÿóÿòÿóÿòÿîÿïÿîÿïÿíÿîÿñÿñÿòÿ÷ÿóÿóÿöÿòÿóÿóÿôÿòÿñÿóÿòÿõÿóÿóÿïÿðÿöÿíÿîÿõÿõÿóÿòÿõÿñÿîÿòÿðÿíÿíÿïÿðÿíÿïÿïÿîÿðÿòÿòÿòÿôÿóÿõÿôÿóÿóÿòÿòÿôÿðÿñÿõÿîÿëÿðÿóÿõÿ÷ÿöÿ÷ÿþÿúÿþÿýÿüÿÿÿûÿûÿþÿûÿüÿÿÿÿÿÿ     ÿÿÿÿÿüÿÿÿýÿûÿûÿ÷ÿøÿüÿøÿúÿýÿûÿÿÿÿÿýÿÿÿýÿÿÿÿÿÿÿýÿþÿþÿÿÿûÿýÿÿÿýÿüÿýÿÿÿüÿÿÿýÿý    !!!"%&$$'$&)'&$')%%""&##%!" $%# !  ÿþÿÿÿÿÿÿÿÿÿÿÿýÿþÿûÿûÿýÿýÿûÿûÿüÿúÿûÿþÿþÿýÿþÿýÿüÿüÿþÿûÿþÿýÿùÿúÿüÿûÿùÿüÿÿÿýÿýÿÿÿüÿþÿþÿÿÿÿ   ÿÿÿþÿþÿýÿûÿûÿüÿùÿûÿûÿûÿùÿøÿûÿûÿùÿûÿûÿüÿýÿùÿýÿýÿùÿûÿûÿúÿûÿüÿúÿúÿúÿùÿøÿüÿüÿúÿùÿùÿüÿûÿùÿûÿøÿøÿ÷ÿöÿöÿöÿöÿõÿöÿ÷ÿ÷ÿ÷ÿöÿ÷ÿ÷ÿ÷ÿúÿøÿ÷ÿøÿöÿ÷ÿ÷ÿõÿöÿùÿõÿòÿôÿõÿöÿ÷ÿ÷ÿ÷ÿøÿùÿùÿûÿûÿùÿýÿýÿúÿúÿüÿûÿùÿüÿúÿûÿûÿúÿûÿûÿûÿýÿýÿþÿÿ      ÿÿÿÿÿÿÿÿÿþÿþÿÿÿþÿþÿýÿûÿüÿûÿúÿúÿùÿúÿúÿùÿøÿøÿ÷ÿöÿöÿ÷ÿ÷ÿ÷ÿ÷ÿ÷ÿ÷ÿøÿøÿ÷ÿùÿúÿùÿùÿúÿùÿùÿøÿùÿ÷ÿ÷ÿúÿûÿùÿùÿúÿúÿúÿùÿøÿùÿûÿøÿ÷ÿøÿøÿöÿ÷ÿ÷ÿöÿöÿ÷ÿùÿ÷ÿøÿùÿ÷ÿ÷ÿøÿøÿøÿøÿøÿ÷ÿöÿ÷ÿ÷ÿöÿöÿøÿöÿöÿøÿùÿøÿøÿúÿûÿùÿúÿúÿüÿüÿûÿûÿûÿûÿüÿûÿûÿûÿûÿûÿûÿúÿüÿýÿüÿýÿýÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿýÿýÿþÿýÿüÿûÿúÿûÿüÿûÿûÿüÿûÿûÿüÿýÿüÿüÿüÿýÿüÿüÿüÿüÿüÿýÿýÿýÿýÿýÿüÿüÿýÿþÿýÿýÿþÿýÿüÿýÿýÿüÿýÿýÿûÿüÿüÿûÿûÿüÿüÿûÿüÿüÿüÿüÿüÿýÿüÿüÿüÿüÿüÿüÿûÿûÿüÿüÿûÿûÿûÿûÿûÿûÿýÿýÿüÿýÿüÿýÿþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿþÿþÿýÿýÿýÿþÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿÿÿþÿþÿÿÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿþÿþÿÿÿþÿþÿÿÿÿÿþÿþÿþÿþÿþÿÿÿÿÿþÿþÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿÿÿÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿfftease-2.5.2.git20121005/examples/blue3.scale0000644000076500007650000000046412067450034017056 0ustar hanshans27.5000 33.6875 41.2672 50.5523 61.9266 75.8601 92.9286 113.8375 139.4509 170.8274 209.2635 256.3478 314.0261 384.6820 471.2354 577.2634 707.1477 866.2559 1061.1635 1299.9252 1592.4084 1950.7003 2389.6079 2927.2697 3585.9054 4392.7341 5381.0992 6591.8465 8075.0120 9891.8897 12117.5649 14844.0170 18183.9208 fftease-2.5.2.git20121005/examples/m3M3.scale0000644000076500007650000000047712067452034016571 0ustar hanshans27.5000 33.0000 41.2500 49.5000 61.8750 74.2500 92.8125 111.3750 139.2188 167.0625 208.8281 250.5938 313.2422 375.8906 469.8633 563.8359 704.7949 845.7539 1057.1924 1268.6309 1585.7886 1902.9463 2378.6829 2854.4194 3568.0243 4281.6292 5352.0364 6422.4437 8028.0547 9633.6656 12042.0820 14450.4984 18063.1230 21675.7476 fftease-2.5.2.git20121005/examples/m3chord.scale0000644000076500007650000000072712067452034017407 0ustar hanshans27.5000 33.0000 36.6667 44.0000 48.8889 55.0000 66.0000 73.3333 88.0000 97.7778 110.0000 132.0000 146.6667 176.0000 195.5556 220.0000 264.0000 293.3333 352.0000 391.1111 440.0000 528.0000 586.6667 704.0000 782.2222 880.0000 1056.0000 1173.3333 1408.0000 1564.4444 1760.0000 2112.0000 2346.6667 2816.0000 3128.8889 3520.0000 4224.0000 4693.3333 5632.0000 6257.7778 7040.0000 8448.0000 9386.6667 11264.0000 12515.5556 14080.0000 16896.0000 18773.3333 22528.0000 25031.1111 fftease-2.5.2.git20121005/examples/octfifth.scale0000644000076500007650000000027412067452034017653 0ustar hanshans27.5000 41.2500 55.0000 82.5000 110.0000 165.0000 220.0000 330.0000 440.0000 660.0000 880.0000 1320.0000 1760.0000 2640.0000 3520.0000 5280.0000 7040.0000 10560.0000 14080.0000 21120.0000 fftease-2.5.2.git20121005/examples/scale1.pl0000644000076500007650000000041612067452034016537 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "m3M3.scale"; open(OUT, ">$file"); $base = 27.5; @ints = (1.2, 1.25); $phs = 0; while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= $ints[$phs++]; $phs %= 2; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale2.pl0000644000076500007650000000037612067452034016545 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "4th.scale"; open(OUT, ">$file"); $base = 27.5; @ints = (1.2, 1.25); $phs = 0; while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= 1.33333333333; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale3.pl0000644000076500007650000000033012067452034016534 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "blue3.scale"; open(OUT, ">$file"); $base = 27.5; while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= 1.225; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale4.pl0000644000076500007650000000035312067452034016542 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "13et.scale"; open(OUT, ">$file"); $base = 27.5; $mult = 2 ** (1/13); while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= $mult; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale5.pl0000644000076500007650000000035312067452034016543 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "24et.scale"; open(OUT, ">$file"); $base = 27.5; $mult = 2 ** (1/24); while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= $mult; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale6.pl0000644000076500007650000000042112067452034016540 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "octfifth.scale"; open(OUT, ">$file"); $base = 27.5; @ints = (1.5, 4/3); $phs = 0; while( $base < 22050 ){ printf OUT "%.4f\n", $base; $base *= $ints[$phs++]; $phs %= 2; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/scale7.pl0000644000076500007650000000057712067452034016555 0ustar hanshans#!/usr/local/bin/perl # -*-Perl-*- $file = "m3chord.scale"; open(OUT, ">$file"); $base = 27.5; @ints = (1.2, 9/8, 1.2, 9/8, 9/8); @ints = (1, 1.2, 4/3, 1.2 * (4/3), 16/9); $phs = 0; $octmult = 1; while( $val < 22050 ){ for $i (0..$#ints){ $val = $base * $ints[$i] * $octmult; printf OUT "%.4f\n", $val; } $octmult *= 2; } close $file; print "wrote to $file\n"; fftease-2.5.2.git20121005/examples/test.scale0000644000076500007650000000002112067452034017012 0ustar hanshans10. 11. 12 13 17 fftease-2.5.2.git20121005/fft.c0000644000076500007650000000663012067450034014141 0ustar hanshans#include "fftease.h" /* If forward is true, rfft replaces 2*N real data points in x with N complex values representing the positive frequency half of their Fourier spectrum, with x[1] replaced with the real part of the Nyquist frequency value. If forward is false, rfft expects x to contain a positive frequency spectrum arranged as before, and replaces it with 2*N real values. N MUST be a power of 2. */ void rfft( float *x, int N, int forward ) { float c1,c2, h1r,h1i, h2r,h2i, wr,wi, wpr,wpi, temp, theta; float xr,xi; int i, i1,i2,i3,i4, N2p1; static int first = 1; /*float PI, TWOPI;*/ void cfft(); if ( first ) { first = 0; } theta = PI/N; wr = 1.; wi = 0.; c1 = 0.5; if ( forward ) { c2 = -0.5; cfft( x, N, forward ); xr = x[0]; xi = x[1]; } else { c2 = 0.5; theta = -theta; xr = x[1]; xi = 0.; x[1] = 0.; } wpr = -2.*pow( sin( 0.5*theta ), 2. ); wpi = sin( theta ); N2p1 = (N<<1) + 1; for ( i = 0; i <= N>>1; i++ ) { i1 = i<<1; i2 = i1 + 1; i3 = N2p1 - i2; i4 = i3 + 1; if ( i == 0 ) { h1r = c1*(x[i1] + xr ); h1i = c1*(x[i2] - xi ); h2r = -c2*(x[i2] + xi ); h2i = c2*(x[i1] - xr ); x[i1] = h1r + wr*h2r - wi*h2i; x[i2] = h1i + wr*h2i + wi*h2r; xr = h1r - wr*h2r + wi*h2i; xi = -h1i + wr*h2i + wi*h2r; } else { h1r = c1*(x[i1] + x[i3] ); h1i = c1*(x[i2] - x[i4] ); h2r = -c2*(x[i2] + x[i4] ); h2i = c2*(x[i1] - x[i3] ); x[i1] = h1r + wr*h2r - wi*h2i; x[i2] = h1i + wr*h2i + wi*h2r; x[i3] = h1r - wr*h2r + wi*h2i; x[i4] = -h1i + wr*h2i + wi*h2r; } wr = (temp = wr)*wpr - wi*wpi + wr; wi = wi*wpr + temp*wpi + wi; } if ( forward ) x[1] = xr; else cfft( x, N, forward ); } /* cfft replaces float array x containing NC complex values (2*NC float values alternating real, imagininary, etc.) by its Fourier transform if forward is true, or by its inverse Fourier transform if forward is false, using a recursive Fast Fourier transform method due to Danielson and Lanczos. NC MUST be a power of 2. */ void cfft( float *x, int NC, int forward ) { float wr,wi, wpr,wpi, theta, scale; int mmax, ND, m, i,j, delta; void bitreverse(); ND = NC<<1; bitreverse( x, ND ); for ( mmax = 2; mmax < ND; mmax = delta ) { delta = mmax<<1; theta = TWOPI/( forward? mmax : -mmax ); wpr = -2.*pow( sin( 0.5*theta ), 2. ); wpi = sin( theta ); wr = 1.; wi = 0.; for ( m = 0; m < mmax; m += 2 ) { register float rtemp, itemp; for ( i = m; i < ND; i += delta ) { j = i + mmax; rtemp = wr*x[j] - wi*x[j+1]; itemp = wr*x[j+1] + wi*x[j]; x[j] = x[i] - rtemp; x[j+1] = x[i+1] - itemp; x[i] += rtemp; x[i+1] += itemp; } wr = (rtemp = wr)*wpr - wi*wpi + wr; wi = wi*wpr + rtemp*wpi + wi; } } /* scale output */ scale = forward ? 1./ND : 2.; { register float *xi=x, *xe=x+ND; while ( xi < xe ) *xi++ *= scale; } } /* bitreverse places float array x containing N/2 complex values into bit-reversed order */ void bitreverse( float *x, int N ) { float rtemp,itemp; int i,j, m; for ( i = j = 0; i < N; i += 2, j += m ) { if ( j > i ) { rtemp = x[j]; itemp = x[j+1]; /* complex exchange */ x[j] = x[i]; x[j+1] = x[i+1]; x[i] = rtemp; x[i+1] = itemp; } for ( m = N>>1; m >= 2 && j >= m; m >>= 1 ) j -= m; } } fftease-2.5.2.git20121005/fft4.c0000644000076500007650000001354412067450034014227 0ustar hanshans#include #include "fftease.h" void init_rdft(int n, int *ip, float *w) { int nw, nc; void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); nw = n >> 2; makewt(nw, ip, w); nc = n >> 2; makect(nc, ip, w + nw); return; } void rdft(int n, int isgn, float *a, int *ip, float *w) { int j, nw, nc; float xi; void bitrv2(int n, int *ip, float *a), cftsub(int n, float *a, float *w), rftsub(int n, float *a, int nc, float *c); nw = ip[0]; nc = ip[1]; if (isgn < 0) { a[1] = 0.5 * (a[1] - a[0]); a[0] += a[1]; for (j = 3; j <= n - 1; j += 2) { a[j] = -a[j]; } if (n > 4) { rftsub(n, a, nc, w + nw); bitrv2(n, ip + 2, a); } cftsub(n, a, w); for (j = 1; j <= n - 1; j += 2) { a[j] = -a[j]; } } else { if (n > 4) { bitrv2(n, ip + 2, a); } cftsub(n, a, w); if (n > 4) { rftsub(n, a, nc, w + nw); } xi = a[0] - a[1]; a[0] += a[1]; a[1] = xi; } } void bitrv2(int n, int *ip, float *a) { int j, j1, k, k1, l, m, m2; float xr, xi; ip[0] = 0; l = n; m = 1; while ((m << 2) < l) { l >>= 1; for (j = 0; j <= m - 1; j++) { ip[m + j] = ip[j] + l; } m <<= 1; } if ((m << 2) > l) { for (k = 1; k <= m - 1; k++) { for (j = 0; j <= k - 1; j++) { j1 = (j << 1) + ip[k]; k1 = (k << 1) + ip[j]; xr = a[j1]; xi = a[j1 + 1]; a[j1] = a[k1]; a[j1 + 1] = a[k1 + 1]; a[k1] = xr; a[k1 + 1] = xi; } } } else { m2 = m << 1; for (k = 1; k <= m - 1; k++) { for (j = 0; j <= k - 1; j++) { j1 = (j << 1) + ip[k]; k1 = (k << 1) + ip[j]; xr = a[j1]; xi = a[j1 + 1]; a[j1] = a[k1]; a[j1 + 1] = a[k1 + 1]; a[k1] = xr; a[k1 + 1] = xi; j1 += m2; k1 += m2; xr = a[j1]; xi = a[j1 + 1]; a[j1] = a[k1]; a[j1 + 1] = a[k1 + 1]; a[k1] = xr; a[k1 + 1] = xi; } } } } void cftsub(int n, float *a, float *w) { int j, j1, j2, j3, k, k1, ks, l, m; float wk1r, wk1i, wk2r, wk2i, wk3r, wk3i; float x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i; l = 2; while ((l << 1) < n) { m = l << 2; for (j = 0; j <= l - 2; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x0r - x2r; a[j2 + 1] = x0i - x2i; a[j1] = x1r - x3i; a[j1 + 1] = x1i + x3r; a[j3] = x1r + x3i; a[j3 + 1] = x1i - x3r; } if (m < n) { wk1r = w[2]; for (j = m; j <= l + m - 2; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; a[j2] = x2i - x0i; a[j2 + 1] = x0r - x2r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * (x0r - x0i); a[j1 + 1] = wk1r * (x0r + x0i); x0r = x3i + x1r; x0i = x3r - x1i; a[j3] = wk1r * (x0i - x0r); a[j3 + 1] = wk1r * (x0i + x0r); } k1 = 1; ks = -1; for (k = (m << 1); k <= n - m; k += m) { k1++; ks = -ks; wk1r = w[k1 << 1]; wk1i = w[(k1 << 1) + 1]; wk2r = ks * w[k1]; wk2i = w[k1 + ks]; wk3r = wk1r - 2 * wk2i * wk1i; wk3i = 2 * wk2i * wk1r - wk1i; for (j = k; j <= l + k - 2; j += 2) { j1 = j + l; j2 = j1 + l; j3 = j2 + l; x0r = a[j] + a[j1]; x0i = a[j + 1] + a[j1 + 1]; x1r = a[j] - a[j1]; x1i = a[j + 1] - a[j1 + 1]; x2r = a[j2] + a[j3]; x2i = a[j2 + 1] + a[j3 + 1]; x3r = a[j2] - a[j3]; x3i = a[j2 + 1] - a[j3 + 1]; a[j] = x0r + x2r; a[j + 1] = x0i + x2i; x0r -= x2r; x0i -= x2i; a[j2] = wk2r * x0r - wk2i * x0i; a[j2 + 1] = wk2r * x0i + wk2i * x0r; x0r = x1r - x3i; x0i = x1i + x3r; a[j1] = wk1r * x0r - wk1i * x0i; a[j1 + 1] = wk1r * x0i + wk1i * x0r; x0r = x1r + x3i; x0i = x1i - x3r; a[j3] = wk3r * x0r - wk3i * x0i; a[j3 + 1] = wk3r * x0i + wk3i * x0r; } } } l = m; } if (l < n) { for (j = 0; j <= l - 2; j += 2) { j1 = j + l; x0r = a[j] - a[j1]; x0i = a[j + 1] - a[j1 + 1]; a[j] += a[j1]; a[j + 1] += a[j1 + 1]; a[j1] = x0r; a[j1 + 1] = x0i; } } } void rftsub(int n, float *a, int nc, float *c) { int j, k, kk, ks; float wkr, wki, xr, xi, yr, yi; ks = (nc << 2) / n; kk = 0; for (k = (n >> 1) - 2; k >= 2; k -= 2) { j = n - k; kk += ks; wkr = 0.5 - c[kk]; wki = c[nc - kk]; xr = a[k] - a[j]; xi = a[k + 1] + a[j + 1]; yr = wkr * xr - wki * xi; yi = wkr * xi + wki * xr; a[k] -= yr; a[k + 1] -= yi; a[j] += yr; a[j + 1] -= yi; } } void makewt(int nw, int *ip, float *w) { void bitrv2(int n, int *ip, float *a); int nwh, j; float delta, x, y; ip[0] = nw; ip[1] = 1; if (nw > 2) { nwh = nw >> 1; delta = atan(1.0) / nwh; w[0] = 1; w[1] = 0; w[nwh] = cos(delta * nwh); w[nwh + 1] = w[nwh]; for (j = 2; j <= nwh - 2; j += 2) { x = cos(delta * j); y = sin(delta * j); w[j] = x; w[j + 1] = y; w[nw - j] = y; w[nw - j + 1] = x; } bitrv2(nw, ip + 2, w); } } void makect(int nc, int *ip, float *c) { int nch, j; float delta; ip[1] = nc; if (nc > 1) { nch = nc >> 1; delta = atan(1.0) / nch; c[0] = 0.5; c[nch] = 0.5 * cos(delta * nch); for (j = 1; j <= nch - 1; j++) { c[j] = 0.5 * cos(delta * j); c[nc - j] = 0.5 * sin(delta * j); } } } fftease-2.5.2.git20121005/fftease-meta.pd0000644000076500007650000000035612067452034016105 0ustar hanshans#N canvas 15 49 200 200 10; #N canvas 25 49 420 300 META 1; #X text 13 41 NAME fftease; #X text 10 25 AUTHOR Eric Lyon and Christopher Penrose; #X text 10 10 VERSION 2.5.2.git20121005; #X text 10 60 LICENSE MIT; #X restore 10 10 pd META; fftease-2.5.2.git20121005/fftease-system-help.pd0000644000076500007650000000040612067452034017425 0ustar hanshans#N canvas 629 262 450 300 10; #X obj 123 118 fftease-system; #X text 37 31 [fftease-system] is a support object for the FFTease library. It is used for sending standard control messages to configure various objects. Open the object itself for more information:; fftease-2.5.2.git20121005/fftease-system.pd0000644000076500007650000000243412067450034016500 0ustar hanshans#N canvas 724 87 493 474 10; #X obj 174 207 outlet; #X msg 174 167 overlap \$1; #X msg 161 122 2; #X msg 202 121 4; #X msg 235 120 8; #X msg 297 165 winfac \$1; #X msg 282 120 1; #X msg 323 119 2; #X msg 355 118 4; #X msg 36 175 fftinfo; #X msg 102 155 mute \$1; #X obj 102 120 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 45 27 FFT size is overlap times the fftease subpatch block size (256 in our examples). With a blocksize of 256 and overlap 4 your FFT size is 1024 Higher overlap generally gives higher quality \, but CPU load is proportional to overlap \, so if you double the overlap \, you double the CPU load.; #X text 33 245 winfac determines the ratio between the FFT size and an input window that funnels samples into the FFT. Roughly speaking \, smaller window sizes (minimum is 1) give tighter temporal response \, but higher sizes can improve frequency performance \, especially with lower FFT sizes.; #X text 29 337 It is recommended that overlap and winfac only be used when the DACs are off. They can potentially crash Pd when the DACs are active.; #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 0 0; #X connect 6 0 5 0; #X connect 7 0 5 0; #X connect 8 0 5 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X connect 11 0 10 0; fftease-2.5.2.git20121005/fftease.h0000644000076500007650000000410112067450034014773 0ustar hanshans#include #include #include #include /* The new improved fftease.h */ #define getbytes t_getbytes #define freebytes t_freebytes #define resizebytes t_resizebytes #define FFTEASE_ANNOUNCEMENT "- a member of FFTease 2.52" #ifndef PI #define PI 3.141592653589793115997963468544185161590576171875 #endif #ifndef TWOPI #define TWOPI 6.28318530717958623199592693708837032318115234375 #endif #define MAX_N (16384) #define MAX_N2 (MAX_N/2) #define MAX_Nw (MAX_N * 4) void convert(float *S, float *C, int N2, float *lastphase, float fundamental, float factor ); void unconvert( float *C, float *S, int N2, float *lastphase, float fundamental, float factor ); void rfft( float *x, int N, int forward ); void cfft( float *x, int NC, int forward ); void bitreverse( float *x, int N ); void fold( float *I, float *W, int Nw, float *O, int N, int n ); void init_rdft(int n, int *ip, float *w); void rdft(int n, int isgn, float *a, int *ip, float *w); void bitrv2(int n, int *ip, float *a); void cftsub(int n, float *a, float *w); void rftsub(int n, float *a, int nc, float *c); void makewt(int nw, int *ip, float *w); void makect(int nc, int *ip, float *c); void leanconvert( float *S, float *C, int N2 ); void leanunconvert( float *C, float *S, int N2 ); void makewindows( float *H, float *A, float *S, int Nw, int N, int I ); void makehamming( float *H, float *A, float *S, int Nw, int N, int I,int odd ); void makehanning( float *H, float *A, float *S, int Nw, int N, int I,int odd ); void overlapadd( float *I, int N, float *W, float *O, int Nw, int n ); void bloscbank( float *S, float *O, int D, float iD, float *lf, float *la, float *bindex, float *tab, int len, float synt, int lo, int hi ); float randf( float min, float max ); int randi( int min, int max ); int power_of_two(int test); void freebytes2(void *fatso, size_t nbytes); void *getbytes2(size_t nbytes); void *resizebytes2(void *old, size_t oldsize, size_t newsize); void limit_fftsize(int *N, int *Nw, char *OBJECT_NAME); /* THE FUNCTIONS */ fftease-2.5.2.git20121005/fftease_setup.c0000644000076500007650000000014612067450034016213 0ustar hanshansvoid fftease_setup(void) { post("Loaded FFTease Library"); printf("Loaded FFTease Library(2)"); } fftease-2.5.2.git20121005/fold.c0000644000076500007650000000077012067450034014305 0ustar hanshans#include "fftease.h" /* * multiply current input I by window W (both of length Nw); * using modulus arithmetic, fold and rotate windowed input * into output array O of (FFT) length N according to current * input time n */ void fold( float *I, float *W, int Nw, float *O, int N, int n ) { int i; for ( i = 0; i < N; i++ ) O[i] = 0.; while ( n < 0 ) n += N; n %= N; for ( i = 0; i < Nw; i++ ) { O[n] += I[i]*W[i]; if ( ++n == N ) n = 0; } } fftease-2.5.2.git20121005/leaker~-help.pd0000644000076500007650000000607412067450034016134 0ustar hanshans#N canvas 718 386 500 440 10; #N canvas 0 22 462 312 leaker-block 0; #X obj 194 143 outlet~; #X obj 198 186 block~ 256; #X obj 194 112 leaker~ 4 1; #X obj 165 52 inlet~; #X obj 212 52 inlet~; #X obj 280 60 inlet; #X obj 329 97 inlet; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 2 1; #X connect 5 0 2 2; #X connect 6 0 2 0; #X restore 96 168 pd leaker-block; #X msg 255 182 \; pd dsp \$1; #X obj 255 159 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 96 221 dac~; #X floatatom 162 113 5 0 1 0 - xfade -; #X obj 100 254 hsl 128 15 0 1 0 0 xfade empty xfade -2 -6 0 8 -260372 -1 -1 10400 1; #N canvas 0 22 466 316 messages 1; #X msg 40 116 upsieve; #X msg 52 138 downsieve; #X msg 69 163 randsieve; #X obj 40 262 outlet; #X obj 105 220 fftease-system; #X text 43 90 select sieve characteristic:; #X connect 0 0 3 0; #X connect 1 0 3 0; #X connect 2 0 3 0; #X connect 4 0 3 0; #X restore 196 141 pd messages; #X text 237 254 <- spectral crossfade here; #X obj 16 215 loadbang; #X msg 16 238 0.5; #N canvas 990 218 520 409 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array leaker-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 leaker-sound1; #X obj 227 268 tabplay~ leaker-sound1; #X connect 1 0 11 0; #X connect 3 0 1 0; #X connect 5 0 12 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 11 0 0 0; #X connect 12 0 4 0; #X connect 12 1 6 0; #X restore 96 37 pd playsound1; #N canvas 990 218 516 405 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #N canvas 0 22 450 300 graph2 0; #X array leaker-sound2 2.499e+06 float 2; #X coords 0 1 2.499e+06 -1 200 140 1; #X restore 216 15 graph; #X msg 31 177 read -resize \$1 leaker-sound2; #X obj 227 268 tabplay~ leaker-sound2; #X connect 1 0 11 0; #X connect 2 0 1 0; #X connect 4 0 12 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 11 0 0 0; #X connect 12 0 3 0; #X connect 12 1 5 0; #X restore 129 55 pd playsound2; #X text 38 317 leaker~ combines two input sounds \, with the spectral contribution of each sound determined by an internally maintained sieve and a threshold selection value. At value 0 \, only sound 1 is heard and at value 1 \, only sound 2 is heard. At intermediate values \, parts of each spectrum are aggregated according to the sieve structure which may be specified as upsieve \, downsieve or randsieve.; #X connect 0 0 3 0; #X connect 0 0 3 1; #X connect 2 0 1 0; #X connect 4 0 0 2; #X connect 6 0 0 3; #X connect 8 0 9 0; #X connect 9 0 5 0; #X connect 10 0 0 0; #X connect 11 0 0 1; fftease-2.5.2.git20121005/leaker~.c0000644000076500007650000003014112067450034015015 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *leaker_class; #endif #if PD static t_class *leaker_class; #endif #define OBJECT_NAME "leaker~" typedef struct _leaker { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; float *input1; float *buffer1; float *channel1; float *input2; float *buffer2; float *channel2; int *sieve ; // int inCount; float *Hwin; float *Wanal; float *Wsyn; float *output; /* leaker vars */ float *c_lastphase_in1; float *c_lastphase_in2; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; float mult; float *trigland; int *bitshuffle; short mute; short bypass; short fade_connected; float fade_value; int overlap; int winfac; } t_leaker; static void leaker_free(t_leaker *x); void *leaker_new(t_symbol *msg, short argc, t_atom *argv); //t_int *offset_perform(t_int *w); t_int *leaker_perform(t_int *w); void leaker_dsp(t_leaker *x, t_signal **sp, short *count); void leaker_assist(t_leaker *x, void *b, long m, long a, char *s); void leaker_upsieve(t_leaker *x) ; void leaker_downsieve(t_leaker *x) ; void leaker_randsieve(t_leaker *x) ; void leaker_bypass(t_leaker *x, t_floatarg state); void leaker_mute(t_leaker *x, t_floatarg state); void leaker_float(t_leaker *x, double f); void leaker_init(t_leaker *x, short initialized); void leaker_overlap(t_leaker *x, t_floatarg f); void leaker_winfac(t_leaker *x, t_floatarg f); void leaker_fftinfo(t_leaker *x); #if MSP void main(void) { setup((t_messlist **)&leaker_class, (method)leaker_new, (method)leaker_free, (short)sizeof(t_leaker), 0, A_GIMME, 0); addmess((method)leaker_dsp, "dsp", A_CANT, 0); addmess((method)leaker_assist,"assist",A_CANT,0); addmess((method)leaker_upsieve, "upsieve", 0); addmess((method)leaker_downsieve, "downsieve", 0); addmess((method)leaker_randsieve, "randsieve", 0); addmess((method)leaker_bypass,"bypass",A_DEFFLOAT,0); addmess((method)leaker_mute,"mute",A_DEFFLOAT,0); addmess((method)leaker_overlap,"overlap",A_DEFFLOAT,0); addmess((method)leaker_winfac,"winfac",A_DEFFLOAT,0); addmess((method)leaker_fftinfo,"fftinfo",0); addfloat((method)leaker_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void leaker_tilde_setup(void) { leaker_class = class_new(gensym("leaker~"), (t_newmethod)leaker_new, (t_method)leaker_free ,sizeof(t_leaker), 0,A_GIMME,0); CLASS_MAINSIGNALIN(leaker_class, t_leaker, x_f); class_addmethod(leaker_class, (t_method)leaker_dsp, gensym("dsp"), 0); class_addmethod(leaker_class, (t_method)leaker_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(leaker_class, (t_method)leaker_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(leaker_class, (t_method)leaker_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(leaker_class, (t_method)leaker_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(leaker_class, (t_method)leaker_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(leaker_class, (t_method)leaker_fftinfo, gensym("fftinfo"),0); class_addmethod(leaker_class, (t_method)leaker_upsieve, gensym("upsieve"), 0); class_addmethod(leaker_class, (t_method)leaker_downsieve, gensym("downsieve"),0); class_addmethod(leaker_class, (t_method)leaker_randsieve, gensym("randsieve"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void leaker_overlap(t_leaker *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; leaker_init(x,1); } void leaker_winfac(t_leaker *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; leaker_init(x,2); } void leaker_fftinfo(t_leaker *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void leaker_free( t_leaker *x ){ #if MSP dsp_free((t_pxobject *)x); #endif freebytes(x->c_lastphase_in1,0); freebytes(x->c_lastphase_in2,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input1,0); freebytes(x->input2,0); freebytes(x->Hwin,0); freebytes(x->buffer1,0); freebytes(x->buffer2,0); freebytes(x->channel1,0); freebytes(x->channel2,0); freebytes(x->output,0); freebytes(x->sieve,0); } void leaker_upsieve(t_leaker *x) { int i; for( i = 0; i < x->N2; i++ ){ x->sieve[i] = i + 1; } } void leaker_downsieve(t_leaker *x) { int i; for( i = 0; i < x->N2; i++ ){ x->sieve[i] = x->N2 - i; } } void leaker_randsieve(t_leaker *x) { int i,j; int NSwitch = 100000 ; int temp ; int pos1, pos2; // use better algorithm for( i = 0; i < x->N2; i++ ){ x->sieve[i] = i + 1; } for( i = 0; i < NSwitch; i++ ){ pos1 = rand() % x->N2; pos2 = rand() % x->N2; temp = x->sieve[pos2]; x->sieve[pos2] = x->sieve[pos1]; x->sieve[pos1] = temp ; } } void leaker_bypass(t_leaker *x, t_floatarg state) { x->bypass = (short)state; } void leaker_mute(t_leaker *x, t_floatarg state) { x->mute = (short)state; } void leaker_assist (t_leaker *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input 1");break; case 1: sprintf(dst,"(signal) Input 2");break; case 2: sprintf(dst,"(signal/float) Crossfade Position (0.0 - 1.0)");break; } } else if (msg==2) { sprintf(dst,"(signal) Output "); } } void *leaker_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_leaker *x = (t_leaker *)newobject(leaker_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_leaker *x = (t_leaker *)pd_new(leaker_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->D = sys_getblksize(); x->R = sys_getsr(); if(!x->D) x->D = 256; if(!x->R) x->R = 44100; x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!x->overlap) x->overlap = 4; if(!x->winfac) x->winfac = 1; leaker_init(x,0); return (x); } void leaker_init(t_leaker *x, short initialized) { int i; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 2; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized) { x->mute = 0; x->bypass = 0; x->fade_connected = 0; x->fade_value = 0; x->input1 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer1 = (float *) getbytes(MAX_N * sizeof(float)); x->channel1 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->input2 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer2 = (float *) getbytes(MAX_N * sizeof(float)); x->channel2 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->Wanal = (float *) getbytes(MAX_Nw * sizeof(float)); x->Wsyn = (float *) getbytes(MAX_Nw * sizeof(float)); x->Hwin = (float *) getbytes(MAX_Nw * sizeof(float)); x->output = (float *) getbytes(MAX_Nw * sizeof(float)); x->bitshuffle = (int *) getbytes (MAX_N * 2 * sizeof( int )); x->trigland = (float *) getbytes(MAX_N * 2 * sizeof( float )); x->sieve = (int *) getbytes((MAX_N2 + 1) * sizeof(int)); x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float)); } memset((char *)x->input1,0,x->Nw); memset((char *)x->input2,0,x->Nw); memset((char *)x->output,0,x->Nw); memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); if(initialized != 2){ for(i = 0; i < x->N2; i++){ x->sieve[i] = i; } } } t_int *leaker_perform(t_int *w) { int i,j,odd,even; float a1,a2,b1,b2; t_leaker *x = (t_leaker *) (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]); t_int n = w[6]; float fade_value = x->fade_value; float *input1 = x->input1; float *input2 = x->input2; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *output = x->output; float *buffer1 = x->buffer1; float *buffer2 = x->buffer2; float *channel1 = x->channel1; float *channel2 = x->channel2; int *sieve = x->sieve; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; /* dereference struncture */ if( x->mute) { while(n--){ *out++ = 0.; } return (w+7); } if( x->bypass ) { while(n--){ *out++ = *in1++; } return (w+7); } #if MSP if(x->fade_connected) fade_value = *in3++ * (float) N2; #endif #if PD fade_value = *in3++ * (float) N2; #endif inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input1[j] = input1[j+D]; input2[j] = input2[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input1[j] = *in1++; input2[j] = *in2++; } fold(input1, Wanal, Nw, buffer1, N, inCount); fold(input2, Wanal, Nw, buffer2, N, inCount); rdft(N, 1, buffer1, bitshuffle, trigland); rdft(N, 1, buffer2, bitshuffle, trigland); for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; if( fade_value <= 0 || fade_value < sieve[i] ){ a1 = ( i == N2 ? *(buffer1+1) : *(buffer1+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(buffer1+odd) ); *(channel1+even) = hypot( a1, b1 ) ; *(channel1+odd) = -atan2( b1, a1 ); *(buffer1+even) = *(channel1+even) * cos(*(channel1+odd)); if ( i != N2 ){ *(buffer1+odd) = -(*(channel1+even)) * sin(*(channel1+odd)); } } else { a2 = ( i == N2 ? *(buffer2+1) : *(buffer2+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(buffer2+odd) ); *(channel1+even) = hypot( a2, b2 ) ; *(channel1+odd) = -atan2( b2, a2 ); *(buffer1+even) = *(channel1+even) * cos(*(channel1+odd) ); if ( i != N2 ){ *(buffer1+odd) = -(*(channel1+even)) * sin( *(channel1+odd) ); } } } rdft( N, -1, buffer1, bitshuffle, trigland ); overlapadd( buffer1, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; x->inCount = inCount % Nw; return (w+7); } void leaker_dsp(t_leaker *x, t_signal **sp, short *count) { long i; #if MSP x->fade_connected = count[2]; #endif if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; leaker_init(x,1); } dsp_add(leaker_perform, 6, x, sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[3]->s_vec,sp[0]->s_n); } #if MSP void leaker_float(t_leaker *x, double f) { int inlet = x->x_obj.z_in; if( inlet == 2 && f >= 0 && f <= 1){ x->fade_value = f * (float) x->N2; } } #endif fftease-2.5.2.git20121005/leanconvert.c0000644000076500007650000000057212067450034015701 0ustar hanshans#include "fftease.h" void leanconvert( float *S, float *C, int N2 ) { int real, imag, amp, phase; float a, b; int i; double hypot(), atan2(); for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; a = ( i == N2 ? S[1] : S[real] ); b = ( i == 0 || i == N2 ? 0. : S[imag] ); C[amp] = hypot( a, b ); C[phase] = -atan2( b, a ); } } fftease-2.5.2.git20121005/leanunconvert.c0000644000076500007650000000120212067450034016233 0ustar hanshans#include "fftease.h" /* unconvert essentially undoes what convert does, i.e., it turns N2+1 PAIRS of amplitude and frequency values in C into N2 PAIR of complex spectrum data (in rfft format) in output array S; sampling rate R and interpolation factor I are used to recompute phase values from frequencies */ void leanunconvert( float *C, float *S, int N2 ) { double cos(), sin(); int real, imag, amp, phase; register int i; for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; S[real] = *(C+amp) * cos( *(C+phase) ); if ( i != N2 ) S[imag] = -*(C+amp) * sin( *(C+phase) ); } } fftease-2.5.2.git20121005/limit_fftsize.c0000644000076500007650000000052012067450034016222 0ustar hanshans#include "fftease.h" extern void post(const char *fmt, ...); void limit_fftsize(int *N, int *Nw, char *OBJECT_NAME) { if(*N > MAX_N){ // post("%s: N set to maximum FFT size of %d",OBJECT_NAME,MAX_N); *N = MAX_N; } if(*Nw > MAX_Nw){ // post("%s: Nw set to maximum window size of %d",OBJECT_NAME,MAX_Nw); *Nw = MAX_Nw; } }fftease-2.5.2.git20121005/makewindows.c0000644000076500007650000000510312067450034015704 0ustar hanshans#include "fftease.h" void makewindows( float *H, float *A, float *S, int Nw, int N, int I ) { int i ; float sum ; for ( i = 0 ; i < Nw ; i++ ) H[i] = A[i] = S[i] = 0.54 - 0.46*cos( TWOPI*i/(Nw - 1) ) ; if ( Nw > N ) { float x ; x = -(Nw - 1)/2. ; for ( i = 0 ; i < Nw ; i++, x += 1. ) if ( x != 0. ) { A[i] *= N*sin( PI*x/N )/(PI*x) ; if ( I ) S[i] *= I*sin( PI*x/I )/(PI*x) ; } } for ( sum = i = 0 ; i < Nw ; i++ ) sum += A[i] ; for ( i = 0 ; i < Nw ; i++ ) { float afac = 2./sum ; float sfac = Nw > N ? 1./afac : afac ; A[i] *= afac ; S[i] *= sfac ; } if ( Nw <= N && I ) { for ( sum = i = 0 ; i < Nw ; i += I ) sum += S[i]*S[i] ; for ( sum = 1./sum, i = 0 ; i < Nw ; i++ ) S[i] *= sum ; } } void makehamming( float *H, float *A, float *S, int Nw, int N, int I, int odd ) { int i; float sum ; if (odd) { for ( i = 0 ; i < Nw ; i++ ) H[i] = A[i] = S[i] = sqrt(0.54 - 0.46*cos( TWOPI*i/(Nw - 1) )); } else { for ( i = 0 ; i < Nw ; i++ ) H[i] = A[i] = S[i] = 0.54 - 0.46*cos( TWOPI*i/(Nw - 1) ); } if ( Nw > N ) { float x ; x = -(Nw - 1)/2. ; for ( i = 0 ; i < Nw ; i++, x += 1. ) if ( x != 0. ) { A[i] *= N*sin( PI*x/N )/(PI*x) ; if ( I ) S[i] *= I*sin( PI*x/I )/(PI*x) ; } } for ( sum = i = 0 ; i < Nw ; i++ ) sum += A[i] ; for ( i = 0 ; i < Nw ; i++ ) { float afac = 2./sum ; float sfac = Nw > N ? 1./afac : afac ; A[i] *= afac ; S[i] *= sfac ; } if ( Nw <= N && I ) { for ( sum = i = 0 ; i < Nw ; i += I ) sum += S[i]*S[i] ; for ( sum = 1./sum, i = 0 ; i < Nw ; i++ ) S[i] *= sum ; } } void makehanning( float *H, float *A, float *S, int Nw, int N, int I, int odd ) { int i; float sum ; if (odd) { for ( i = 0 ; i < Nw ; i++ ) H[i] = A[i] = S[i] = sqrt(0.5 * (1. + cos(PI + TWOPI * i / (Nw - 1)))); } else { for ( i = 0 ; i < Nw ; i++ ) H[i] = A[i] = S[i] = 0.5 * (1. + cos(PI + TWOPI * i / (Nw - 1))); } if ( Nw > N ) { float x ; x = -(Nw - 1)/2. ; for ( i = 0 ; i < Nw ; i++, x += 1. ) if ( x != 0. ) { A[i] *= N*sin( PI*x/N )/(PI*x) ; if ( I ) S[i] *= I*sin( PI*x/I )/(PI*x) ; } } for ( sum = i = 0 ; i < Nw ; i++ ) sum += A[i] ; for ( i = 0 ; i < Nw ; i++ ) { float afac = 2./sum ; float sfac = Nw > N ? 1./afac : afac ; A[i] *= afac ; S[i] *= sfac ; } if ( Nw <= N && I ) { for ( sum = i = 0 ; i < Nw ; i += I ) sum += S[i]*S[i] ; for ( sum = 1./sum, i = 0 ; i < Nw ; i++ ) S[i] *= sum ; } } fftease-2.5.2.git20121005/manual/0000755000076500007650000000000012067452122014466 5ustar hanshansfftease-2.5.2.git20121005/manual/code-notes.rtf0000644000076500007650000000241412067450034017244 0ustar hanshans{\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf230 {\fonttbl\f0\fswiss\fcharset77 Helvetica;\f1\fnil\fcharset77 LucidaGrande;} {\colortbl;\red255\green255\blue255;} \margl1440\margr1440\vieww9000\viewh8400\viewkind0 \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\ql\qnatural\pardirnatural \f0\fs24 \cf0 notes:\ \ improved memory cleaning in resident\ \ disabled residency_buffer if no argument given\ \ fixed dentist factor of two bug for bin number\ \ 30.11.05\ \ gave presidency an "int" function to avoid int error\ \ fixed potential memory bug in all objects and recompiled for OS X. Now must reinstall code for Pd and Windows FFTease.\ \ \ removed FFTease Lite from helpfiles and \f1 FFTease-objectlist.txt\ \ 31.11.05\ \ compiled stuff for windows:\ removed "old memory" message from hacked miller code in reanimator\ \ fixed residency_buffer:\ added overlap\ fixed problem with initiating sampling\ \ added residency_buffer helpfile gain slider\ residency_buffer: return 0 instead of return if no argument\ \ residency: modified helpfile\ \ resent:\ fixed no sync out bug when mute is on\ \ scrape: fixed helpfile\ \ swinger: fixed helpfile\ \ dentist: fixed sync bug on mute\ \ disarray: fixed mute bug, helpfile\ \ drown: fixed mute bug\ }fftease-2.5.2.git20121005/mindwarp~-help.pd0000644000076500007650000001154112067450034016505 0ustar hanshans#N canvas 61 22 766 791 10; #X obj 384 435 dac~; #X floatatom 124 121 5 0.1 3 2 transpose transpose -; #X msg 500 486 \; pd dsp \$1; #X obj 500 467 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 85 512 hsl 128 15 0.1 4 0 0 empty empty empty -2 -6 0 8 -261285 -1 -1 1600 1; #N canvas 0 22 494 344 messages 0; #X obj 154 185 outlet; #X obj 154 136 fftease-system; #X connect 1 0 0 0; #X restore 210 338 pd messages; #X obj 227 512 hsl 128 15 0 0.01 0 0 empty empty empty -2 -6 0 8 -227712 -1 -1 0 1; #X obj 224 538 s thresh; #X obj 82 538 s transpose; #X obj 82 460 loadbang; #X msg 82 491 1; #N canvas 0 22 550 400 mindwarp-block 0; #X obj 27 158 outlet~; #X obj 27 42 inlet~; #X obj 73 14 inlet; #X obj 120 49 inlet; #X obj 213 69 inlet; #X text 107 105 args: warp factor \, shape width \, overlap \, winfac ; #X obj 27 85 mindwarp~ 1 16; #X obj 28 183 block~ 256; #X connect 1 0 6 0; #X connect 2 0 6 1; #X connect 3 0 6 2; #X connect 4 0 6 0; #X connect 6 0 0 0; #X restore 96 364 pd mindwarp-block; #N canvas 1171 182 470 320 pvoc-block 0; #X obj 102 141 pvoc~; #X obj 102 199 outlet~; #X obj 102 50 inlet~; #X obj 117 94 inlet; #X obj 233 94 inlet; #X obj 270 115 block~ 256; #X obj 164 95 inlet; #X connect 0 0 1 0; #X connect 2 0 0 0; #X connect 3 0 0 1; #X connect 4 0 0 0; #X connect 6 0 0 2; #X restore 96 194 pd pvoc-block; #X text 176 274 warp factor; #X floatatom 172 316 5 1 16 0 - - -; #N canvas 990 218 520 409 playsound 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #N canvas 0 22 450 300 graph3 0; #X array mindwarp-sound1 302338 float 2; #X coords 0 1 302337 -1 200 140 1; #X restore 231 21 graph; #X obj 227 268 tabplay~ mindwarp-sound1; #X msg 31 177 read -resize \$1 mindwarp-sound1; #X connect 1 0 13 0; #X connect 2 0 1 0; #X connect 4 0 12 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 12 0 3 0; #X connect 12 1 5 0; #X connect 13 0 0 0; #X restore 96 38 pd playsound; #N canvas 0 22 494 344 messages 0; #X obj 154 185 outlet; #X obj 302 145 fftease-system; #X floatatom 65 105 5 0 0 0 - - -; #X msg 65 126 highfreq \$1; #X floatatom 201 94 5 0 0 0 - - -; #X msg 201 112 lowfreq \$1; #X msg 65 83 8000; #X obj 65 61 loadbang; #X msg 201 73 0; #X obj 201 51 loadbang; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 0 0; #X connect 4 0 5 0; #X connect 5 0 0 0; #X connect 6 0 2 0; #X connect 7 0 6 0; #X connect 8 0 4 0; #X connect 9 0 8 0; #X restore 182 174 pd messages; #X msg 384 314 set mindwarp-raw; #X obj 384 409 receive~ mindwarp-warped; #X msg 384 333 set mindwarp-pvoc; #X msg 384 352 set mindwarp-warped; #X obj 129 396 send~ mindwarp-warped; #X obj 119 228 send~ mindwarp-pvoc; #X obj 108 73 send~ mindwarp-raw; #X text 380 290 select listening point:; #X text 503 314 original sound; #X text 511 335 pvoc transposed; #X text 523 352 post-pvoc formant-adjusted; #X text 82 577 mindwarp~ performs spectral envelope warping. It can be used to correct for the formant shifting effects of pitch-scaling. The warp factor is tuned to warp spectra to compensate for directly corresponding pitch-scaling values. For example \, if you have pitch-scaled a signal by a factor of two \, increasing its frequency content by an octave \, by providing mindwarp~ with a warp factor of 2 and the pitch-scaled signal \, mindwarp~ will restore the spectral formant of the signal to an estimation of the shape present in the original unscaled signal. Currently \, warp factor values are restricted to the range [1/16 ... 16.]. mindwarp~ utilizes frequency shaping to perform its duty. It can be fun to decorrelate the warp factor from the transposition factor.; #X text 190 32 <- first load a soundfile here; #X floatatom 153 156 5 0 0 0 - - -; #X floatatom 134 275 5 0.1 20 0 - - -; #X obj 134 252 r transpose; #X text 214 316 shape width; #X obj 153 137 r thresh; #X msg 224 476 1e-05; #X obj 172 296 r shapewidth; #N canvas 0 22 454 304 init 0; #X obj 95 88 loadbang; #X msg 95 116 16; #X obj 95 155 s shapewidth; #X obj 198 155 s transpose; #X msg 198 120 1; #X connect 0 0 1 0; #X connect 0 0 4 0; #X connect 1 0 2 0; #X connect 4 0 3 0; #X restore 501 518 pd init; #X connect 1 0 12 1; #X connect 3 0 2 0; #X connect 4 0 8 0; #X connect 5 0 11 3; #X connect 6 0 7 0; #X connect 9 0 10 0; #X connect 9 0 35 0; #X connect 10 0 4 0; #X connect 11 0 21 0; #X connect 12 0 11 0; #X connect 12 0 22 0; #X connect 14 0 11 2; #X connect 15 0 12 0; #X connect 15 0 23 0; #X connect 16 0 12 3; #X connect 17 0 18 0; #X connect 18 0 0 0; #X connect 18 0 0 1; #X connect 19 0 18 0; #X connect 20 0 18 0; #X connect 30 0 12 2; #X connect 31 0 11 1; #X connect 32 0 31 0; #X connect 34 0 30 0; #X connect 35 0 6 0; #X connect 36 0 14 0; fftease-2.5.2.git20121005/mindwarp~.c0000644000076500007650000003424412067450034015403 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *mindwarp_class; #endif #if PD static t_class *mindwarp_class; #endif #define OBJECT_NAME "mindwarp~" #define MAX_WARP 16.0 /* 12.11.05 fixed divide-by-zero bug */ typedef struct _mindwarp { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int warpConnected; int widthConnected; int *bitshuffle; float warpFactor; float shapeWidth; float *Wanal; float *Wsyn; float *inputOne; float *Hwin; float *bufferOne; float *channelOne; float *newChannel; float *newAmplitudes; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_mindwarp; /* msp function prototypes */ void *mindwarp_new(t_symbol *s, int argc, t_atom *argv); t_int *mindwarp_perform(t_int *w); void mindwarp_dsp(t_mindwarp *x, t_signal **sp, short *count); void mindwarp_float(t_mindwarp *x, double myFloat); void mindwarp_assist(t_mindwarp *x, void *b, long m, long a, char *s); void mindwarp_dest(t_mindwarp *x, double f); void mindwarp_init(t_mindwarp *x, short initialized); void mindwarp_free(t_mindwarp *x); void mindwarp_mute(t_mindwarp *x, t_floatarg toggle); void mindwarp_fftinfo(t_mindwarp *x); void mindwarp_overlap(t_mindwarp *x, t_floatarg o); void mindwarp_winfac(t_mindwarp *x, t_floatarg o); void mindwarp_tilde_setup(void); #if MSP void mindwarp_float( t_mindwarp *x, double df ) { float myFloat = (float)df; int inlet = x->x_obj.z_in; //post("float input to mindwarp: %f",myFloat); if ( inlet == 1 ) { x->warpFactor = myFloat; if ( x->warpFactor > MAX_WARP ) x->warpFactor = MAX_WARP; if ( x->warpFactor < (1. / MAX_WARP) ) x->warpFactor = (1. / MAX_WARP); } if ( inlet == 2 ) { if ( myFloat >= 1. && myFloat <= (double) x->N ) x->shapeWidth = myFloat; } } void main(void) { setup( (struct messlist **) &mindwarp_class, (method) mindwarp_new, (method) mindwarp_free, (short) sizeof(t_mindwarp), 0, A_GIMME, 0); addmess((method)mindwarp_dsp, "dsp", A_CANT, 0); addmess((method)mindwarp_assist,"assist",A_CANT,0); addmess((method)mindwarp_mute,"mute", A_FLOAT, 0); addmess((method)mindwarp_overlap,"overlap", A_FLOAT, 0); addmess((method)mindwarp_winfac,"winfac", A_FLOAT, 0); addmess((method)mindwarp_fftinfo,"fftinfo", 0); addfloat((method)mindwarp_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void mindwarp_tilde_setup(void) { mindwarp_class = class_new(gensym("mindwarp~"), (t_newmethod)mindwarp_new, (t_method)mindwarp_free ,sizeof(t_mindwarp), 0,A_GIMME,0); CLASS_MAINSIGNALIN(mindwarp_class, t_mindwarp, x_f); class_addmethod(mindwarp_class, (t_method)mindwarp_dsp, gensym("dsp"), 0); class_addmethod(mindwarp_class, (t_method)mindwarp_assist, gensym("assist"), 0); class_addmethod(mindwarp_class, (t_method)mindwarp_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(mindwarp_class, (t_method)mindwarp_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(mindwarp_class, (t_method)mindwarp_mute, gensym("mute"), A_FLOAT,0); class_addmethod(mindwarp_class, (t_method)mindwarp_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif /* diagnostic messages for Max */ void mindwarp_assist (t_mindwarp *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Formant Input"); break; case 1: sprintf(dst,"(signal/float) Warp Factor"); break; case 2: sprintf(dst,"(signal/float) Shape Width"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Mindwarp Output"); } } void *mindwarp_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_mindwarp *x = (t_mindwarp *) newobject(mindwarp_class); dsp_setup((t_pxobject *)x, 3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_mindwarp *x = (t_mindwarp *)pd_new(mindwarp_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* args: warpfactor, shape width, overlap, window factor */ x->warpFactor = atom_getfloatarg(0,argc,argv); x->shapeWidth = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } if(x->warpFactor <= 0 || x->warpFactor > 100.0) x->warpFactor = 1.0; if(x->shapeWidth <= 0 || x->shapeWidth > 64) x->shapeWidth = 3.0; x->vs = sys_getblksize(); x->R = sys_getsr(); mindwarp_init(x,0); return (x); } void mindwarp_init(t_mindwarp *x, short initialized) { x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->Wanal = (float *) getbytes (MAX_Nw * sizeof(float)); x->Wsyn = (float *) getbytes (MAX_Nw * sizeof(float)); x->Hwin = (float *) getbytes (MAX_Nw * sizeof(float)); x->inputOne = (float *) getbytes (MAX_Nw * sizeof(float)); x->bufferOne = (float *) getbytes (MAX_N * sizeof(float)); x->channelOne = (float *) getbytes (MAX_N+2 * sizeof(float)); x->newAmplitudes = (float *) getbytes (((MAX_N2 + 1) * 16) * sizeof(float)); x->newChannel = (float *) getbytes ((MAX_N + 1) * sizeof(float)); x->output = (float *) getbytes (MAX_Nw * sizeof(float)); x->bitshuffle = (int *) getbytes (MAX_N * 2 * sizeof(int)); x->trigland = (float *) getbytes (MAX_N * 2 * sizeof(float)); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1); } void mindwarp_free(t_mindwarp *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->bufferOne,0); freebytes(x->channelOne,0); freebytes(x->newAmplitudes,0); freebytes(x->newChannel,0); freebytes(x->output,0); } t_int *mindwarp_perform(t_int *w) { int i,j, bindex, inCount, R, N, N2, D, Nw, invert = 1, shapeWidth, remainingWidth, newLength, even, odd, *bitshuffle; float maxamp, threshMult = 1., warpFactor, mult, cutoff, filterMult, a1, b1, interpIncr, interpPhase, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *newChannel, *newAmplitudes, *trigland; /* get our inlets and outlets */ t_mindwarp *x = (t_mindwarp *) (w[1]); t_float *inOne = (t_float *) (w[2]); t_float *vec_warpFactor = (t_float *) (w[3]); t_float *vec_shapeWidth = (t_float *) (w[4]); t_float *out = (t_float *)(w[5]); t_int n = w[6]; short *connected = x->connected; if(x->mute){ while(n--) *out++ = 0.0; return w+7; } warpFactor = connected[1] ? *vec_warpFactor : x->warpFactor; shapeWidth = connected[2] ? (int) (*vec_shapeWidth) : (int) x->shapeWidth; if(warpFactor <= 0.0){ warpFactor = 0.1; error("zero warp factor reported"); } /* dereference structure */ inputOne = x->inputOne; bufferOne = x->bufferOne; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; newChannel = x->newChannel; newAmplitudes = x->newAmplitudes; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; cutoff = (float) N2 * .9; filterMult = .00001; /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) inputOne[j] = inputOne[j+D]; for ( j = Nw - D; j < Nw; j++ ) inputOne[j] = *inOne++; /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); /* replace signal one's phases with those of signal two */ *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); } /* set the number of expected new amplitudes */ if(warpFactor <= 0){ error("bad warp, resetting"); warpFactor = 1.0; } newLength = (int) ((float) N2 / warpFactor); if(newLength <= 0){ error("bad length: resetting"); newLength = 1.0; } interpIncr = (float) N2 / (float) newLength; interpPhase = 0.; /* do simple linear interpolation on magnitudes */ for ( bindex=0; bindex < newLength; bindex++ ) { int localbindex = ((int) interpPhase) << 1; float lower = *(channelOne + localbindex), upper = *(channelOne + localbindex + 2), diff = interpPhase - ( (float) ( (int) interpPhase ) ); *(newAmplitudes+bindex) = lower + ( ( upper - lower ) * diff ); interpPhase += interpIncr; } /* replace magnitudes with warped values */ if (warpFactor > 1.) { int until = (int) ( cutoff / warpFactor ); for ( bindex=0; bindex < until; bindex++ ) { register int amp = bindex<<1; *(newChannel+amp) = *(newAmplitudes+bindex); } /* filter remaining spectrum as spectral envelope has shrunk */ for ( bindex=until; bindex < N2; bindex++ ) { register int amp = bindex<<1; *(newChannel+amp) *= filterMult; } } //OK /* spectral envelope has enlarged, no post filtering is necessary */ else { for ( bindex=0; bindex <= N2; bindex++ ) { register int amp = bindex<<1; *(newChannel+amp) = *(newAmplitudes+bindex); } } /* constrain our shapeWidth value */ if ( shapeWidth > N2 ) shapeWidth = N2; if ( shapeWidth < 1 ) shapeWidth = 1; /* lets just shape the entire signal by the shape width */ for ( i=0; i < N; i += shapeWidth << 1 ) { float amplSum = 0., freqSum = 0., factor = 1.0; for ( j = 0; j < shapeWidth << 1; j += 2 ) { amplSum += *(newChannel+i+j); freqSum += *(channelOne+i+j); } if (amplSum < 0.000000001) factor = 0.000000001; /* this can happen, crashing external; now fixed.*/ if( freqSum <= 0 ){ // error("bad freq sum, resetting"); freqSum = 1.0; } else factor = amplSum / freqSum; for ( j = 0; j < shapeWidth << 1; j += 2 ) *(channelOne+i+j) *= factor; } /* copy remaining magnitudes (fixed shadowed variable warning by renaming bindex)*/ if ( (remainingWidth = N2 % shapeWidth) ) { int lbindex = (N2 - remainingWidth) << 1; float amplSum = 0., freqSum = 0., factor; for ( j = 0; j < remainingWidth << 1; j += 2 ) { amplSum += *(newChannel+lbindex+j); freqSum += *(channelOne+lbindex+j); } if (amplSum < 0.000000001) factor = 0.000000001; else factor = amplSum / freqSum; for ( j = 0; j < remainingWidth << 1; j += 2 ) *(channelOne+bindex+j) *= factor; } /* convert from polar to cartesian */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void mindwarp_mute(t_mindwarp *x, t_floatarg toggle) { x->mute = (short)toggle; } void mindwarp_overlap(t_mindwarp *x, t_floatarg o) { if(!fftease_power_of_two((int)o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; mindwarp_init(x,1); } void mindwarp_winfac(t_mindwarp *x, t_floatarg f) { if(!fftease_power_of_two((int)f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; mindwarp_init(x,1); } void mindwarp_fftinfo( t_mindwarp *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void mindwarp_dsp(t_mindwarp *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 3; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 3; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; mindwarp_init(x,1); } dsp_add(mindwarp_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/morphine~-help.pd0000644000076500007650000000674512067450034016517 0ustar hanshans#N canvas 831 409 575 413 10; #N canvas 0 22 454 304 morphine-block 0; #X obj 48 204 block~ 512; #X obj 152 114 morphine~; #X obj 152 69 inlet~; #X obj 201 71 inlet~; #X obj 260 73 inlet; #X obj 314 81 inlet; #X obj 152 202 outlet~; #X connect 1 0 6 0; #X connect 2 0 1 0; #X connect 3 0 1 1; #X connect 4 0 1 2; #X connect 5 0 1 0; #X restore 149 150 pd morphine-block; #N canvas 990 218 520 409 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array morphine-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X msg 31 177 read -resize \$1 morphine-sound1; #X obj 227 268 tabplay~ morphine-sound1; #X text 316 205 comment; #X text 63 132 1 open the sound; #X text 109 245 2 then play it; #X text 304 190 3 loop if you like; #X connect 1 0 8 0; #X connect 3 0 1 0; #X connect 5 0 9 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 8 0 0 0; #X connect 9 0 4 0; #X connect 9 1 6 0; #X restore 149 18 pd playsound1; #N canvas 990 218 520 409 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array morphine-sound2 2.5137e+06 float 2; #X coords 0 1 2.5137e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 316 205 comment; #X text 63 132 1 open the sound; #X text 109 245 2 then play it; #X text 304 190 3 loop if you like; #X obj 227 268 tabplay~ morphine-sound2; #X msg 31 177 read -resize \$1 morphine-sound2; #X connect 1 0 13 0; #X connect 3 0 1 0; #X connect 5 0 12 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 12 0 4 0; #X connect 12 1 6 0; #X connect 13 0 0 0; #X restore 187 42 pd playsound2; #X floatatom 225 119 5 0 0 0 - - -; #X text 223 81 morph index; #N canvas 643 138 458 308 messages 0; #X obj 100 164 outlet; #X msg 100 126 transition \$1; #X obj 103 78 hsl 128 15 -30 0 0 0 empty empty empty -2 -6 0 8 -110787 -1 -1 10900 1; #X text 61 49 exponential transition scalar; #X floatatom 100 106 5 0 0 0 - - -; #X obj 35 26 loadbang; #X msg 35 49 -5; #X obj 177 148 fftease-system; #X connect 1 0 0 0; #X connect 2 0 4 0; #X connect 4 0 1 0; #X connect 5 0 6 0; #X connect 6 0 2 0; #X connect 7 0 0 0; #X restore 295 134 pd messages; #X msg 27 233 \; pd dsp \$1; #X obj 27 216 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 149 209 *~ 1; #X obj 149 261 dac~; #X obj 175 170 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -110787 -1 -1 6700 1; #X floatatom 172 190 5 0 0 0 - - -; #X obj 228 97 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -110787 -1 -1 9400 1; #X text 251 18 <- load sounds here; #X text 289 41 <- and here; #X text 23 291 morphine~ performs spectral morphing \, creating a new spectrum from its two inputs. Values between 0 and 1 are the useful range for the morph index. The progression depends upon the exponential transition scaling value. Progressively smaller negative values will widen the transition space between the two sounds. Larger FFT sizes \, such as 4096 \, produce smoother results.; #X text 310 170 gain; #X connect 0 0 8 0; #X connect 1 0 0 0; #X connect 2 0 0 1; #X connect 3 0 0 2; #X connect 5 0 0 3; #X connect 7 0 6 0; #X connect 8 0 9 0; #X connect 8 0 9 1; #X connect 10 0 11 0; #X connect 11 0 8 1; #X connect 12 0 3 0; fftease-2.5.2.git20121005/morphine~.c0000644000076500007650000003433112067450034015400 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *morphine_class; #endif #if PD static t_class *morphine_class; #endif #define OBJECT_NAME "morphine~" /* Added additional inlet for morphine index -EL */ typedef struct _pickme { int bin; float value; } pickme; typedef struct _morphine { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int *bitshuffle; float morphIndex; float exponScale; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; pickme *picks; pickme *mirror; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_morphine; /* msp function prototypes */ void *morphine_new(t_symbol *s, int argc, t_atom *argv); //t_int *offset_perform(t_int *w); t_int *morphine_perform(t_int *w); void morphine_dsp(t_morphine *x, t_signal **sp, short *count); void morphine_assist(t_morphine *x, void *b, long m, long a, char *s); void morphine_dest(t_morphine *x, double f); int sortIncreasing( const void *a, const void *b ); //int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)()); // avoid warning with legal function pointer prototype int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)(const void *a, const void *b)); void morphine_transition(t_morphine *x, t_floatarg f); void morphine_free(t_morphine *x); void morphine_mute(t_morphine *x, t_floatarg toggle); void morphine_fftinfo(t_morphine *x); void morphine_tilde_setup(void); void morphine_overlap(t_morphine *x, t_floatarg o); void morphine_winfac(t_morphine *x, t_floatarg o); void morphine_init(t_morphine *x, short initialized); int sortIncreasing( const void *a, const void *b ) { if ( ((pickme *) a)->value > ((pickme *) b)->value ) return 1; if ( ((pickme *) a)->value < ((pickme *) b)->value ) return -1; return 0; } #if MSP void main(void) { setup( (struct messlist **) &morphine_class, (void *) morphine_new, (method)morphine_free, (short) sizeof(t_morphine), 0, A_GIMME, 0); addmess((method)morphine_dsp, "dsp", A_CANT, 0); addmess((method)morphine_assist,"assist",A_CANT,0); addmess((method)morphine_transition,"transition", A_FLOAT, 0); addmess((method)morphine_overlap,"overlap", A_FLOAT, 0); addmess((method)morphine_mute,"mute", A_FLOAT, 0); addmess((method)morphine_fftinfo,"fftinfo", 0); addmess((method)morphine_winfac,"winfac",A_FLOAT, 0); addfloat((method)morphine_dest); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); dsp_initclass(); } void morphine_dest(t_morphine *x, double f) { int inlet = x->x_obj.z_in; if(inlet == 2) x->morphIndex = f; // post("index now %f", x->morphIndex); } #endif #if PD void morphine_tilde_setup(void) { morphine_class = class_new(gensym("morphine~"), (t_newmethod)morphine_new, (t_method)morphine_free ,sizeof(t_morphine), 0,A_GIMME,0); CLASS_MAINSIGNALIN(morphine_class, t_morphine, x_f); class_addmethod(morphine_class, (t_method)morphine_dsp, gensym("dsp"), 0); class_addmethod(morphine_class, (t_method)morphine_assist, gensym("assist"), 0); class_addmethod(morphine_class, (t_method)morphine_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(morphine_class, (t_method)morphine_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(morphine_class, (t_method)morphine_mute, gensym("mute"), A_FLOAT,0); class_addmethod(morphine_class, (t_method)morphine_transition, gensym("transition"), A_FLOAT,0); class_addmethod(morphine_class, (t_method)morphine_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif /* diagnostic messages for Max */ void morphine_assist (t_morphine *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input One"); break; case 1: sprintf(dst,"(signal) Input Two"); break; case 2: sprintf(dst,"(signal/float) Morph Index"); break; } } else { if (msg == 2) sprintf(dst,"(signal) output"); } } void morphine_transition(t_morphine *x, t_floatarg f) { x->exponScale = (float)f; } void *morphine_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_morphine *x = (t_morphine *) newobject(morphine_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_morphine *x = (t_morphine *)pd_new(morphine_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: exponent scale, overlap, window factor */ x->exponScale = atom_getfloatarg(0,argc,argv); x->overlap = atom_getfloatarg(1,argc,argv); x->winfac = atom_getfloatarg(2,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } x->vs = sys_getblksize(); x->R = sys_getsr(); morphine_init(x,0); return (x); } void morphine_init(t_morphine *x, short initialized) { int i; int BIGGIE = 32768; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->morphIndex = 0.; x->mute = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->inputOne = (float *) getbytes(MAX_Nw * sizeof(float)); x->inputTwo = (float *) getbytes(MAX_Nw * sizeof(float)); x->bufferOne = (float *) getbytes(MAX_N * sizeof(float)); x->bufferTwo = (float *) getbytes(MAX_N * sizeof(float)); x->channelOne = (float *) getbytes(MAX_N+2 * sizeof(float)); x->channelTwo = (float *) getbytes(MAX_N+2 * sizeof(float)); x->output = (float *) getbytes(MAX_Nw * sizeof(float)); x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int)); x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float)); x->picks = (pickme *) getbytes(((MAX_N2)+1) * sizeof(pickme)); x->mirror = (pickme *) getbytes(((MAX_N2)+1) * sizeof(pickme)); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } t_int *morphine_perform(t_int *w) { int i,j, inCount, R, N, N2, D, Nw, lookupIndex, even, odd, *bitshuffle; float maxamp, threshMult = 1., mult, morphIndex, exponScale, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; pickme *picks, *mirror; /* get our inlets and outlets */ t_morphine *x = (t_morphine *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *vec_morphIndex = (t_float *)(w[4]); t_float *out = (t_float *)(w[5]); t_int n = w[6]; short *connected = x->connected; if(x->mute){ while(n--) *out++ = 0.0; return w+7; } /* dereference structure */ inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; picks = x->picks; mirror = x->mirror; morphIndex = x->morphIndex; exponScale = x->exponScale; morphIndex = connected[2] ? *vec_morphIndex : x->morphIndex; // post("connected %d index %f stored index %f",connected[2],morphIndex, x->morphIndex); if ( morphIndex < 0 ) morphIndex = 0.; else { if ( morphIndex > 1. ) morphIndex = 1.; } /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); /* find amplitude differences between home and visitors */ (picks+i)->value = fabs( *(channelOne+even) - *(channelTwo+even) ); (picks+i)->bin = i; } /* sort our differences in ascending order */ qsortE( (char *) picks, (int) N2+1, (int) sizeof(pickme), sortIncreasing ); /* now we create an effective mirror of the sorted distribution. we will assure that the initial transition will be made from small spectral differences (when the sort behavior is increasing) and the ending transition will also be made from small spectral differences */ for ( i=0; i <= N2; i += 2 ) { (mirror+(i/2))->bin = (picks+i)->bin; (mirror+(i/2))->value = (picks+i)->value; } for ( i=1; i <= N2; i += 2 ) { (mirror+(N2-(i/2)))->bin = (picks+i)->bin; (mirror+(N2-(i/2)))->value = (picks+i)->value; } /* calculate our morphIndex from an exponential function based on exponScale */ if (exponScale == 0.) lookupIndex = (int) (( (float) N2 ) * morphIndex); else { if ( morphIndex < .5 ) { lookupIndex = (int) ( ((float) N2) * (( (1. - exp( exponScale * morphIndex * 2. )) / (1. - exp( exponScale )) ) * .5) ); } else { lookupIndex = (int) ( ((float) N2) * ( .5 + (( (1. - exp( -exponScale * (morphIndex - .5) * 2. )) / (1. - exp( -exponScale )) ) * .5) ) ); } } // post("%d", lookupIndex); /* choose the bins that are least different first */ for ( i=0; i <= lookupIndex; i++ ) { even = ((mirror+i)->bin)<<1, odd = (((mirror+i)->bin)<<1) + 1; *(channelOne+even) = *(channelTwo+even); *(channelOne+odd) = *(channelTwo+odd); } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void morphine_free(t_morphine *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->inputTwo,0); freebytes(x->bufferOne,0); freebytes(x->bufferTwo,0); freebytes(x->channelOne,0); freebytes(x->channelTwo,0); freebytes(x->picks,0); freebytes(x->mirror,0); freebytes(x->output,0); } void morphine_fftinfo( t_morphine *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void morphine_overlap(t_morphine *x, t_floatarg df) { int o = (int)df; if(!fftease_power_of_two(o)){ error("%d is not a power of two",o); return; } x->overlap = (int)o; morphine_init(x,1); } void morphine_winfac(t_morphine *x, t_floatarg df) { int wf = (int) df; if(!fftease_power_of_two(wf)){ error("%d is not a power of two",wf); return; } x->winfac = wf; morphine_init(x,1); } void morphine_mute(t_morphine *x, t_floatarg toggle) { x->mute = (short)toggle; } void morphine_dsp(t_morphine *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 3; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 3; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; morphine_init(x,1); } dsp_add(morphine_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/multyq~-help.pd0000644000076500007650000000547012067450034016223 0ustar hanshans#N canvas 224 36 657 848 10; #X msg 360 574 \; pd dsp \$1; #X obj 360 548 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 136 366 dac~; #X obj 180 295 nbx 5 14 -1e+37 1e+37 0 0 empty out-gain empty 0 -6 0 10 -262144 -1 -1 0.0551181 256; #X obj 29 394 hsl 128 15 60 600 0 0 cf1 empty cf1 -2 -6 0 8 -235882 -1 -1 5400 1; #X obj 49 151 noise~; #N canvas 0 22 502 352 multyq-block 0; #X obj 71 352 block~ 256; #X obj 28 95 inlet~; #X obj 193 169 inlet; #X obj 72 299 outlet~; #X obj 72 256 multyq~ 4 1; #X obj 249 239 inlet; #X obj 66 143 inlet; #X obj 72 182 inlet; #X obj 78 217 inlet; #X obj 110 142 inlet; #X obj 116 181 inlet; #X obj 122 216 inlet; #X text 67 105 [cf \, bw \, gain] triplets; #X obj 182 141 inlet~; #X obj 199 189 inlet; #X connect 1 0 4 0; #X connect 2 0 4 8; #X connect 4 0 3 0; #X connect 5 0 4 0; #X connect 6 0 4 1; #X connect 7 0 4 2; #X connect 8 0 4 3; #X connect 9 0 4 4; #X connect 10 0 4 5; #X connect 11 0 4 6; #X connect 13 0 4 7; #X connect 14 0 4 9; #X restore 136 261 pd multyq-block; #X floatatom 146 7 5 0 0 2 - cf1 -; #X floatatom 156 22 5 0 0 2 - bw1 -; #X floatatom 166 37 5 0 0 2 - gain1 -; #X obj 30 433 hsl 128 15 0.01 0.5 0 0 bw1 empty bw1 -2 -6 0 8 -235882 -1 -1 7000 1; #X obj 30 471 hsl 128 15 0 20 0 0 gain1 empty gain1 -2 -6 0 8 -235882 -1 -1 7900 1; #X obj 136 314 *~ 0.05; #X obj 190 595 hsl 128 15 0 1 0 0 out-gain empty out-gain -2 -6 0 8 -44646 -1 -1 700 1; #X obj 31 518 hsl 128 15 600 2000 0 0 cf2 empty cf2 -2 -6 0 8 -235882 -1 -1 2300 1; #X obj 31 557 hsl 128 15 0.01 0.5 0 0 bw2 empty bw2 -2 -6 0 8 -235882 -1 -1 8100 1; #X obj 31 595 hsl 128 15 -1 20 0 0 gain2 empty gain2 -2 -6 0 8 -235882 -1 -1 6600 1; #X floatatom 176 56 5 0 0 2 - cf2 -; #X floatatom 186 73 5 0 0 2 - bw2 -; #X floatatom 196 92 5 0 0 2 - gain2 -; #X obj 206 111 phasor~ 2; #X obj 206 134 *~ 2000; #X obj 206 157 +~ 1500; #X obj 246 452 hsl 128 15 0.01 0.5 0 0 bw3 empty bw3 -2 -6 0 8 -125810 -1 -1 3900 1; #X obj 247 485 hsl 128 15 -1 20 0 0 gain3 empty gain3 -2 -6 0 8 -125810 -1 -1 5400 1; #X floatatom 216 185 5 0 0 0 - bw3 -; #X floatatom 226 213 5 0 0 0 - gain3 -; #X obj 236 238 fftease-system; #X text 29 643 multyq~ is a four band equalizer. Gain values below 0 create notches rather than peaks \, but only go as far as -1.0. Bandwidth is from 0 to 1.0. Only three bands are used in this example \, but cpu usage is the same regardless of how many are used. As the filter is FFT-based \, its performance is spotty in the low frequency range. ; #X connect 1 0 0 0; #X connect 3 0 12 1; #X connect 5 0 6 0; #X connect 6 0 12 0; #X connect 7 0 6 1; #X connect 8 0 6 2; #X connect 9 0 6 3; #X connect 12 0 2 0; #X connect 12 0 2 1; #X connect 17 0 6 4; #X connect 18 0 6 5; #X connect 19 0 6 6; #X connect 20 0 21 0; #X connect 21 0 22 0; #X connect 22 0 6 7; #X connect 25 0 6 8; #X connect 26 0 6 9; #X connect 27 0 6 10; fftease-2.5.2.git20121005/multyq~.c0000644000076500007650000004100012067450034015101 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *multyq_class; #endif #if PD static t_class *multyq_class; #endif #define OBJECT_NAME "multyq~" typedef struct _multyq { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // float mult; float *trigland; int *bitshuffle; // for multyQ float cf1; float gainfac1; float bw1; float cf2; float gainfac2; float bw2; float cf3; float gainfac3; float bw3; float cf4; float gainfac4; float bw4; float *rcos; float *filt; float *freqs; int rcoslen; // short in2_connected; short in3_connected; short in4_connected; short in5_connected; short in6_connected; short in7_connected; short in8_connected; short in9_connected; short in10_connected; short in11_connected; short in12_connected; short in13_connected; short please_update; short always_update; short mute; short bypass; int overlap; int winfac; } t_multyq; void *multyq_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *multyq_perform(t_int *w); void multyq_dsp(t_multyq *x, t_signal **sp, short *count); void multyq_assist(t_multyq *x, void *b, long m, long a, char *s); void multyq_bypass(t_multyq *x, t_floatarg state); void multyq_mute(t_multyq *x, t_floatarg state); void update_filter_function(t_multyq *x); void multyq_float(t_multyq *x, double f); void filtyQ( float *S, float *C, float *filtfunc, int N2 ); void multyq_init(t_multyq *x, short initialized); void multyq_free(t_multyq *x); void multyq_fftinfo(t_multyq *x); void multyq_overlap(t_multyq *x, t_floatarg f); void multyq_winfac(t_multyq *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&multyq_class, (method)multyq_new, (method)multyq_free, (short)sizeof(t_multyq), 0, A_GIMME, 0); addmess((method)multyq_dsp, "dsp", A_CANT, 0); addmess((method)multyq_assist,"assist",A_CANT,0); addmess((method)multyq_bypass,"bypass",A_DEFFLOAT,0); addmess((method)multyq_mute,"mute",A_DEFFLOAT,0); addmess((method)multyq_overlap,"overlap",A_DEFFLOAT,0); addmess((method)multyq_winfac,"winfac",A_DEFFLOAT,0); addmess((method)multyq_fftinfo,"fftinfo",0); addfloat((method)multyq_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void multyq_tilde_setup(void) { multyq_class = class_new(gensym("multyq~"), (t_newmethod)multyq_new, (t_method)multyq_free ,sizeof(t_multyq), 0,A_GIMME,0); CLASS_MAINSIGNALIN(multyq_class, t_multyq, x_f); class_addmethod(multyq_class,(t_method)multyq_dsp,gensym("dsp"),0); class_addmethod(multyq_class,(t_method)multyq_mute,gensym("mute"),A_FLOAT,0); class_addmethod(multyq_class,(t_method)multyq_bypass,gensym("bypass"),A_FLOAT,0); class_addmethod(multyq_class,(t_method)multyq_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(multyq_class,(t_method)multyq_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(multyq_class,(t_method)multyq_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void multyq_free(t_multyq *x) { #if MSP dsp_free((t_pxobject *)x); #endif freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->bitshuffle,0); freebytes(x->trigland,0); freebytes(x->rcos,0); freebytes(x->freqs,0); freebytes(x->filt,0); } void multyq_overlap(t_multyq *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; multyq_init(x,1); } void multyq_winfac(t_multyq *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; multyq_init(x,2); } void multyq_fftinfo(t_multyq *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void *multyq_new(t_symbol *s, int argc, t_atom *argv) { int i; #if MSP t_multyq *x = (t_multyq *)newobject(multyq_class); dsp_setup((t_pxobject *)x,13); outlet_new((t_pxobject *)x, "signal"); x->x_obj.z_misc |= Z_NO_INPLACE; #endif #if PD t_multyq *x = (t_multyq *)pd_new(multyq_class); for(i=0; i<12; i++){ inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); } outlet_new(&x->x_obj, gensym("signal")); #endif x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 2; x->D = sys_getblksize(); x->R = sys_getsr(); if(!x->R) x->R = 44100; if(!x->D) x->D = 256; multyq_init(x,0); return (x); } void multyq_init(t_multyq *x, short initialized) { int i; float funda, base; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->mult = 1. / (float) x->N; x->inCount = -(x->Nw); if(!initialized){ x->please_update = 0; x->always_update = 0; x->rcoslen = 8192 ; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->rcos = (float *) getbytes( x->rcoslen * sizeof( float ) ); x->freqs = (float *) getbytes( MAX_N2 * sizeof( float ) ); x->filt = (float *) getbytes( (MAX_N2 + 1) * sizeof( float ) ); x->cf1 = 200.; x->gainfac1 = 0.0; x->bw1 = .15; x->cf2 = 700.; x->gainfac2 = 0.0; x->bw2 = .1; x->cf3 = 3000.; x->gainfac3 = 0.0; x->bw3 = .15; x->cf4 = 12000.; x->gainfac4 = 0.0; x->bw4 = .15; x->mute = 0; x->bypass = 0; for (i = 0; i < x->rcoslen; i++){ x->rcos[i] = .5 - .5 * cos(((float)i/(float)x->rcoslen) * TWOPI); } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); funda = base = (float)x->R /(float)x->N ; for(i = 0; i < x->N2; i++){ x->freqs[i] = base; base += funda; } update_filter_function(x); } t_int *multyq_perform(t_int *w) { int i, j; t_multyq *x = (t_multyq *) (w[1]); short please_update = x->please_update; float *inbuf = (t_float *)(w[2]); float *in2 = (t_float *)(w[3]); float *in3 = (t_float *)(w[4]); float *in4 = (t_float *)(w[5]); float *in5 = (t_float *)(w[6]); float *in6 = (t_float *)(w[7]); float *in7 = (t_float *)(w[8]); float *in8 = (t_float *)(w[9]); float *in9 = (t_float *)(w[10]); float *in10 = (t_float *)(w[11]); float *in11 = (t_float *)(w[12]); float *in12 = (t_float *)(w[13]); float *in13 = (t_float *)(w[14]); float *outbuf = (t_float *)(w[15]); t_int n = w[16]; int inCount = x->inCount; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float *filt = x->filt; float mult = x->mult; int in = x->inCount ; int on = in; if(x->mute) { while (n--){ *outbuf++ = 0.; } return (w+17); } if(x->bypass) { while (n--){ *outbuf++ = *inbuf++; } return (w+17); } #if MSP if( x->in2_connected ){ x->cf1 = *in2++ ; } if( x->in3_connected ){ x->bw1 = *in3++ ; } if( x->in4_connected ){ x->gainfac1 = *in4++ ; } if( x->in5_connected ){ x->cf2 = *in5++ ; } if( x->in6_connected ){ x->bw2 = *in6++ ; } if( x->in7_connected ){ x->gainfac2 = *in7++ ; } if( x->in8_connected ){ x->cf3 = *in8++ ; } if( x->in9_connected ){ x->bw3 = *in9++ ; } if( x->in10_connected ){ x->gainfac3 = *in10++ ; } if( x->in11_connected ){ x->cf4 = *in11++ ; } if( x->in12_connected ){ x->bw4 = *in12++ ; } if( x->in13_connected ){ x->gainfac4 = *in13++; } #endif #if PD x->cf1 = *in2++; x->bw1 = *in3++; x->gainfac1 = *in4++; x->cf2 = *in5++; x->bw2 = *in6++; x->gainfac2 = *in7++; x->cf3 = *in8++; x->bw3 = *in9++; x->gainfac3 = *in10++; x->cf4 = *in11++; x->bw4 = *in12++; x->gainfac4 = *in13++; #endif if(x->always_update) { update_filter_function(x); } else if(please_update) { update_filter_function(x); please_update = 0; } in += D; on += I; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *inbuf++; } fold(input, Wanal, Nw, buffer, N, in); rdft(N, 1, buffer, bitshuffle, trigland); filtyQ(buffer, channel,filt, N2); rdft(N, -1, buffer, bitshuffle, trigland); overlapadd( buffer, N, Wsyn, output, Nw, inCount); for (j = 0; j < D; j++){ *outbuf++ = output[j] * mult; } for (j = 0; j < Nw - D; j++){ output[j] = output[j+D]; } for (j = Nw - D; j < Nw; j++){ output[j] = 0.; } x->inCount = in; x->please_update = please_update; return (w+17); } void multyq_bypass(t_multyq *x, t_floatarg state) { x->bypass = (short)state; } void multyq_mute(t_multyq *x, t_floatarg state) { x->mute = (short)state; } void multyq_dsp(t_multyq *x, t_signal **sp, short *count) { int i; if(x->R != sp[0]->s_sr||x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; multyq_init(x,1); } #if MSP x->in2_connected = count[1]; x->in3_connected = count[2]; x->in4_connected = count[3]; x->in5_connected = count[4]; x->in6_connected = count[5]; x->in7_connected = count[6]; x->in8_connected = count[7]; x->in9_connected = count[8]; x->in10_connected = count[9]; x->in11_connected = count[10]; x->in12_connected = count[11]; x->in13_connected = count[12]; x->always_update = 0; for(i = 1; i < 13; i++) { x->always_update += count[i]; } #endif #if PD x->always_update = 1; #endif dsp_add(multyq_perform, 16, x, sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[3]->s_vec,sp[4]->s_vec, sp[5]->s_vec,sp[6]->s_vec,sp[7]->s_vec,sp[8]->s_vec,sp[9]->s_vec, sp[10]->s_vec,sp[11]->s_vec,sp[12]->s_vec,sp[13]->s_vec,sp[0]->s_n); } void update_filter_function(t_multyq *x) { float funda, curfreq, m1, m2; float lo, hi ; float ploc, gainer; int i; float nyquist = (float)x->R / 2.0; float *filt = x->filt; float *rcos = x->rcos; float *freqs = x->freqs; int rcoslen = x->rcoslen; // sanity if( x->cf1 < 0 ){ x->cf1 = 0; } else if( x->cf1 > nyquist){ x->cf1 = nyquist ; } if( x->bw1 <= .05 ){ x->bw1 = .05; } else if( x->bw1 > 1. ){ x->bw1 = 1.; } if( x->gainfac1 < -1. ){ x->gainfac1 = -1; } if( x->cf2 < 0 ){ x->cf2 = 0; } else if( x->cf2> nyquist){ x->cf2 = nyquist ; } if( x->bw2 <= .05 ){ x->bw2 = .05; } else if( x->bw2 > 1. ){ x->bw2 = 1.; } if( x->gainfac2 < -1. ){ x->gainfac2 = -1; } if( x->cf3 < 0 ){ x->cf3 = 0; } else if( x->cf3 > nyquist){ x->cf3 = nyquist ; } if( x->bw3 <= .05 ){ x->bw3 = .05; } else if( x->bw3 > 1. ){ x->bw3 = 1.; } if( x->gainfac3 < -1. ){ x->gainfac3 = -1; } if( x->cf4 < 0 ){ x->cf4 = 0; } else if( x->cf4 > nyquist){ x->cf4 = nyquist ; } if( x->bw4 <= .05 ){ x->bw4 = .05; } else if( x->bw4 > 1. ){ x->bw4 = 1.; } if( x->gainfac4 < -1. ){ x->gainfac4 = -1; } for( i = 0; i < x->N2; i++ ) { x->filt[i] = 1.0 ; } // filt 1 lo = x->cf1 * (1.0 - x->bw1 ); hi = x->cf1 * (1.0 + x->bw1 ); for( i = 0; i < x->N2; i++ ) { if(freqs[i] >= lo && freqs[i] <= hi){ ploc = (freqs[i] - lo) / (hi - lo); gainer = 1 + x->gainfac1 * rcos[ (int) (ploc * rcoslen) ] ; if( gainer < 0 ){ gainer = 0; } filt[i] *= gainer ; } } // filt 2 lo = x->cf2 * (1.0 - x->bw2 ); hi = x->cf2 * (1.0 + x->bw2 ); for( i = 0; i < x->N2; i++ ) { if( freqs[i] >= lo && freqs[i] <= hi){ ploc = (freqs[i] - lo) / (hi - lo); gainer = 1 + x->gainfac2 * rcos[ (int) (ploc * rcoslen) ] ; if( gainer < 0 ){ gainer = 0; } filt[i] *= gainer ; } } // filt 3 lo = x->cf3 * (1.0 - x->bw3 ); hi = x->cf3 * (1.0 + x->bw3 ); for( i = 0; i < x->N2; i++ ) { if(freqs[i] >= lo && freqs[i] <= hi){ ploc = (freqs[i] - lo) / (hi - lo); gainer = 1 + x->gainfac3 * rcos[ (int) (ploc * rcoslen) ] ; if( gainer < 0 ){ gainer = 0; } filt[i] *= gainer ; } } // filt 4 lo = x->cf4 * (1.0 - x->bw4 ); hi = x->cf4 * (1.0 + x->bw4 ); for( i = 0; i < x->N2; i++ ) { if(freqs[i] >= lo && freqs[i] <= hi){ ploc = (freqs[i] - lo) / (hi - lo); gainer = 1 + x->gainfac4 * rcos[ (int) (ploc * rcoslen) ] ; if( gainer < 0 ){ gainer = 0; } filt[i] *= gainer ; } } } #if MSP void multyq_float(t_multyq *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->cf1 = f; } else if (inlet == 2) { x->bw1 = f; } else if (inlet == 3) { x->gainfac1 = f; } else if (inlet == 4) { x->cf2 = f; } else if (inlet == 5) { x->bw2 = f; } else if (inlet == 6) { x->gainfac2 = f; } else if (inlet == 7) { x->cf3 = f; } else if (inlet == 8) { x->bw3 = f; } else if (inlet == 9) { x->gainfac3 = f; } else if (inlet == 10) { x->cf4 = f; } else if (inlet == 11) { x->bw4 = f; } else if (inlet == 12) { x->gainfac4 = f; } x->please_update = 1; } #endif void multyq_assist (t_multyq *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Cf1");break; case 2: sprintf(dst,"(signal/float) Bw1"); break; case 3: sprintf(dst,"(signal/float) Gain1"); break; case 4: sprintf(dst,"(signal/float) Cf2"); break; case 5: sprintf(dst,"(signal/float) Bw2"); break; case 6: sprintf(dst,"(signal/float) Gain2"); break; case 7: sprintf(dst,"(signal/float) Cf3"); break; case 8: sprintf(dst,"(signal/float) Bw3"); break; case 9: sprintf(dst,"(signal/float) Gain3"); break; case 10: sprintf(dst,"(signal/float) Cf4"); break; case 11: sprintf(dst,"(signal/float) Bw4"); break; case 12: sprintf(dst,"(signal/float) Gain4"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void filtyQ( float *S, float *C, float *filtfunc, int N2 ) { int real, imag, amp, phase; float a, b; int i; float maxamp = 1.; for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; a = ( i == N2 ? S[1] : S[real] ); b = ( i == 0 || i == N2 ? 0. : S[imag] ); C[amp] = hypot( a, b ); C[amp] *= filtfunc[ i ]; C[phase] = -atan2( b, a ); } for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; S[real] = *(C+amp) * cos( *(C+phase) ); if ( i != N2 ) S[imag] = -*(C+amp) * sin( *(C+phase) ); } } fftease-2.5.2.git20121005/overlapadd.c0000644000076500007650000000064112067450034015477 0ustar hanshans/* * input I is a folded spectrum of length N; output O and * synthesis window W are of length Nw--overlap-add windowed, * unrotated, unfolded input data into output O */ #include "fftease.h" void overlapadd( float *I, int N, float *W, float *O, int Nw, int n ) { int i ; while ( n < 0 ) n += N ; n %= N ; for ( i = 0 ; i < Nw ; i++ ) { O[i] += I[n]*W[i] ; if ( ++n == N ) n = 0 ; } } fftease-2.5.2.git20121005/power_of_two.c0000644000076500007650000000120612067450034016065 0ustar hanshans int power_of_two(int test) { int limit = 8192; int compare = 1; // post("testing what we thing is an int:%d",test); do { if(test == compare){ // post("good power of 2 found!"); return 1; } compare *= 2; } while (compare <= limit); return 0; } // we think the above function is shadowed somewhere else int fftease_power_of_two(int test) { int limit = 8192; int compare = 1; // post("testing what we thing is an int:%d",test); do { if(test == compare){ // post("good power of 2 found!"); return 1; } compare *= 2; } while (compare <= limit); return 0; } fftease-2.5.2.git20121005/presidency~-help.pd0000644000076500007650000001616412067450034017037 0ustar hanshans#N canvas 58 237 555 452 10; #N canvas 431 336 551 457 messages 0; #X obj 34 383 outlet; #X floatatom 42 228 5 0 0 2 - size -; #X msg 42 259 size \$1; #X obj 34 87 bng 15 250 50 0 empty trigger trigger_sampling 0 -6 0 8 -262144 -1 -1; #X obj 64 139 s playsound; #X obj 34 115 t b b; #X msg 34 166 acquire_sample; #X msg 85 230 10000; #X obj 280 367 fftease-system; #X text 45 210 resize memory (but with DACs off to be safe); #X obj 291 266 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 320 265 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 349 265 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X obj 291 239 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #N canvas 0 22 462 312 init 0; #X msg 33 61 playthrough 1; #X obj 33 34 loadbang; #X obj 33 103 outlet; #X obj 233 93 loadbang; #X msg 233 114 1; #X obj 233 136 s speed-slider; #X msg 137 61 verbose 0; #X msg 169 142 1; #X obj 169 164 s transpose-slider; #X connect 0 0 2 0; #X connect 1 0 0 0; #X connect 1 0 6 0; #X connect 3 0 4 0; #X connect 3 0 7 0; #X connect 4 0 5 0; #X connect 6 0 2 0; #X connect 7 0 8 0; #X restore 111 335 pd init; #N canvas 260 69 789 579 frequency-boundaries 0; #X msg 283 158 high_freq \$1; #X obj 286 120 hsl 128 15 500 8000 0 0 empty empty empty -2 -6 0 8 -155632 -1 -1 0 1; #X floatatom 283 140 5 0 0 0 - - -; #X text 280 102 highest frequency to resynthesize; #X text 9 364 note: these relate to frequencies in the original sound. If you transpose the resynthesis \, you will go outside these ranges. ; #X obj 4 318 outlet; #X obj 7 117 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -155632 -1 -1 0 1; #X floatatom 4 138 5 0 0 0 - - -; #X msg 4 167 low_freq \$1; #X obj 7 117 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -155632 -1 -1 0 1; #X text -1 98 lowest frequency to resynthesize; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 6 0 7 0; #X connect 7 0 8 0; #X connect 8 0 5 0; #X restore 64 287 pd frequency-boundaries; #N canvas 24 525 634 358 random-behavior 0; #X obj 46 95 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 46 149 random 1000; #X obj 46 187 * 0.001; #X obj 190 101 random 1000; #X obj 190 139 * 0.001; #X obj 190 169 * 3; #X obj 190 196 + 0.05; #X obj 190 46 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 190 73 metro 233; #X obj 46 57 inlet; #X obj 46 243 spigot; #X obj 83 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X obj 190 243 spigot; #X obj 227 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X obj 344 101 random 1000; #X obj 344 139 * 0.001; #X obj 344 73 metro 233; #X obj 344 243 spigot; #X obj 381 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X obj 344 169 * 2; #X obj 344 196 - 1; #X obj 344 50 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 190 19 inlet; #X obj 344 18 inlet; #X obj 344 268 s speed-slider; #X obj 190 268 s transpose-slider; #X obj 46 268 s position-slider; #X obj 479 183 loadbang; #X msg 479 205 1; #X obj 46 121 metro 650; #X connect 0 0 29 0; #X connect 1 0 2 0; #X connect 2 0 10 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 12 0; #X connect 7 0 8 0; #X connect 8 0 3 0; #X connect 9 0 0 0; #X connect 10 0 26 0; #X connect 11 0 10 1; #X connect 12 0 25 0; #X connect 13 0 12 1; #X connect 14 0 15 0; #X connect 15 0 19 0; #X connect 16 0 14 0; #X connect 17 0 24 0; #X connect 18 0 17 1; #X connect 19 0 20 0; #X connect 20 0 17 0; #X connect 21 0 16 0; #X connect 22 0 7 0; #X connect 23 0 21 0; #X connect 27 0 28 0; #X connect 28 0 18 0; #X connect 28 0 13 0; #X connect 28 0 11 0; #X connect 29 0 1 0; #X restore 291 288 pd random-behavior; #X text 36 10 Load a valid soundfile in sound-source \, then hit the sampling trigger below. The resulting recording is stored as a series of FFT frames inside presidency~ available for arbitrary time-access. ; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 3 0 5 0; #X connect 5 0 6 0; #X connect 5 1 4 0; #X connect 6 0 0 0; #X connect 7 0 2 0; #X connect 8 0 0 0; #X connect 10 0 16 0; #X connect 11 0 16 1; #X connect 12 0 16 2; #X connect 13 0 10 0; #X connect 13 0 11 0; #X connect 13 0 12 0; #X connect 14 0 0 0; #X connect 15 0 0 0; #X restore 252 214 pd messages; #X floatatom 156 134 5 0 0 2 speed speed -; #N canvas 0 22 530 380 sound-source 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array presidency-sound1 441202 float 2; #X coords 0 1 441201 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ presidency-sound1; #X msg 31 177 read -resize \$1 presidency-sound1; #X obj 227 219 r playsound; #X connect 2 0 13 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 5 0; #X connect 12 1 7 0; #X connect 13 0 1 0; #X connect 14 0 6 0; #X restore 124 95 pd sound-source; #X msg 301 272 \; pd dsp \$1; #X obj 301 246 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X floatatom 188 163 5 0 1 2 position position -; #X obj 28 47 vsl 15 128 -2 2 0 0 speed speed-slider speed 0 -8 0 8 -253906 -1 -1 9525 1; #X obj 60 47 vsl 15 128 0 1 0 0 position position-slider position 0 -8 0 8 -4094 -1 -1 0 1; #X text 333 214 <- ask me what I can do; #X floatatom 220 194 5 0 1 2 transpose transpose -; #X obj 35 216 vsl 15 128 0.1 2 0 0 transpose transpose-slider transpose 0 -8 0 8 -231210 -1 -1 6016 1; #X msg 29 13 0; #N canvas 81 500 498 348 presidency-block 0; #X obj 28 42 inlet~; #X obj 89 42 inlet~; #X obj 150 42 inlet~; #X obj 313 66 inlet; #X obj 28 140 outlet~; #X obj 28 169 block~ 256; #X text 103 171 FFT size is block~ size times overlap; #X obj 28 99 presidency~ 5000 0 4000 4 1; #X obj 212 42 inlet~; #X text 39 120 args: size \, minfreq \, maxfreq \, overlap \, window factor; #X obj 323 279 outlet; #X obj 323 251 snapshot~; #X obj 378 213 metro 50; #X msg 378 192 1; #X obj 378 156 loadbang; #X connect 0 0 7 0; #X connect 1 0 7 1; #X connect 2 0 7 2; #X connect 3 0 7 0; #X connect 7 0 4 0; #X connect 7 1 11 0; #X connect 8 0 7 3; #X connect 11 0 10 0; #X connect 12 0 11 0; #X connect 13 0 12 0; #X connect 14 0 13 0; #X restore 124 246 pd presidency-block; #X text 128 372 presidency~ follows the residency~ model but uses an oscillator bank for resynthesis and offers independent control of speed \, location and transposition of playback.; #X text 237 94 <- first load a sound here; #X floatatom 252 271 5 0 0 0 - - -; #X text 212 272 sync; #X obj 214 31 hsl 128 15 0 1 0 0 presidency-gain empty gain -2 -6 0 8 -67648 -1 -1 0 1; #X obj 124 322 dac~; #X obj 124 284 *~ 0.25; #X floatatom 168 268 5 0 0 3 - presidency-gain -; #X text 59 14 freeze frame; #X connect 0 0 12 4; #X connect 1 0 12 1; #X connect 2 0 12 0; #X connect 4 0 3 0; #X connect 5 0 12 2; #X connect 9 0 12 3; #X connect 11 0 6 0; #X connect 12 0 19 0; #X connect 12 1 15 0; #X connect 19 0 18 1; #X connect 19 0 18 0; #X connect 20 0 19 1; fftease-2.5.2.git20121005/presidency~.c0000644000076500007650000004712312067450034015727 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *presidency_class; #endif #if PD static t_class *presidency_class; #endif #define OBJECT_NAME "presidency~" typedef struct _presidency { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float **loveboat; float current_frame; float *local_frame; // needs mem allocation in init int framecount; float lo_freq; float hi_freq; float topfreq; float curfreq; float P; int lo_bin; int hi_bin; float i_vector_size; float vector_size; float synthesis_threshold; float pitch_increment; // oscillator float *table; float *bindex; float *lastamp;// stores last amplitudes for each bin float *lastfreq;// stores last frequencies float table_si; int table_length; // float frame_increment ; float fpos; float last_fpos; float tadv; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // faster fft float mult; float *trigland; int *bitshuffle; int read_me; int frames_read; // int MAXFRAMES; short mute; short virgin; short playthrough; short in2_connected; short in3_connected; short in4_connected; int overlap; int winfac; int hopsize; float duration; short lock; short verbose; short override; float sync; } t_presidency; void *presidency_new(t_symbol *s, int argc, t_atom *argv); t_int *presidency_perform(t_int *w); void presidency_dsp(t_presidency *x, t_signal **sp, short *count); void presidency_assist(t_presidency *x, void *b, long m, long a, char *s); void presidency_bangname(t_presidency *x) ; void presidency_playthrough( t_presidency *x, t_floatarg tog) ; void presidency_float(t_presidency *x, double f) ; void presidency_int(t_presidency *x, long i); void presidency_mute(t_presidency *x, t_floatarg tog); void presidency_free(t_presidency *x); void presidency_init(t_presidency *x, short initialized); void presidency_size(t_presidency *x, t_floatarg newsize); void presidency_winfac(t_presidency *x, t_floatarg factor); void presidency_overlap(t_presidency *x, t_floatarg o); void presidency_fftinfo(t_presidency *x) ; void presidency_verbose(t_presidency *x, t_floatarg t); void presidency_acquire_sample(t_presidency *x); void presidency_low_freq(t_presidency *x, t_floatarg f); void presidency_high_freq(t_presidency *x, t_floatarg f); void presidency_calc_bins_from_freqs(t_presidency *x); void presidency_abs_thresh(t_presidency *x, t_floatarg t); #if MSP void main(void) { setup((t_messlist **)&presidency_class, (method)presidency_new, (method)presidency_free, (short)sizeof(t_presidency), 0, A_GIMME,0); addmess((method)presidency_dsp, "dsp", A_CANT, 0); addmess((method)presidency_assist,"assist",A_CANT,0); addfloat((method)presidency_float); addint((method)presidency_int); addbang((method)presidency_bangname); addmess((method)presidency_mute, "mute", A_FLOAT, 0); addmess((method)presidency_fftinfo, "fftinfo", 0); addmess((method)presidency_playthrough, "playthrough", A_DEFFLOAT, 0); addmess((method)presidency_size, "size", A_DEFFLOAT, 0); addmess((method)presidency_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)presidency_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)presidency_verbose, "verbose", A_DEFFLOAT, 0); addmess((method)presidency_low_freq, "low_freq", A_DEFFLOAT, 0); addmess((method)presidency_high_freq, "high_freq", A_DEFFLOAT, 0); addmess((method)presidency_acquire_sample, "acquire_sample", 0); addmess((method)presidency_abs_thresh, "abs_thresh", A_FLOAT, 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void presidency_tilde_setup(void) { presidency_class = class_new(gensym("presidency~"), (t_newmethod)presidency_new, (t_method)presidency_free ,sizeof(t_presidency), 0,A_GIMME,0); CLASS_MAINSIGNALIN(presidency_class, t_presidency, x_f); class_addmethod(presidency_class,(t_method)presidency_dsp,gensym("dsp"),0); class_addmethod(presidency_class,(t_method)presidency_mute,gensym("mute"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_fftinfo,gensym("fftinfo"),0); class_addmethod(presidency_class,(t_method)presidency_playthrough,gensym("playthrough"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_size,gensym("size"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_verbose,gensym("verbose"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_acquire_sample,gensym("acquire_sample"),0); class_addmethod(presidency_class,(t_method)presidency_low_freq,gensym("low_freq"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_high_freq,gensym("high_freq"),A_FLOAT,0); class_addmethod(presidency_class,(t_method)presidency_abs_thresh,gensym("abs_thresh"),A_FLOAT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void presidency_abs_thresh(t_presidency *x, t_floatarg f) { if(f < 0){ error("illegal value for threshold"); return; } x->synthesis_threshold = f; } void presidency_low_freq(t_presidency *x, t_floatarg f) { if(f > x->hi_freq || f < 0){ error("illegal value for low freq"); return; } x->lo_freq = f; presidency_calc_bins_from_freqs(x); } void presidency_high_freq(t_presidency *x, t_floatarg f) { if(f < x->lo_freq || f > x->R/2.0){ error("illegal value for high freq"); return; } x->hi_freq = f; presidency_calc_bins_from_freqs(x); } void presidency_calc_bins_from_freqs(t_presidency *x) { x->hi_bin = 1; x->curfreq = 0; if( x->c_fundamental <= 0){ error("we're not yet fully initialized. Try turning on DACs first"); return; } while( x->curfreq < x->hi_freq ) { ++(x->hi_bin); x->curfreq += x->c_fundamental ; } x->lo_bin = 0; x->curfreq = 0; while( x->curfreq < x->lo_freq ) { ++(x->lo_bin); x->curfreq += x->c_fundamental ; } if( x->hi_bin > x->N2) x->hi_bin = x->N2 ; if(x->lo_bin > x->hi_bin) x->lo_bin = x->hi_bin; // post("hibin: %d lobin %d",x->hi_bin, x->lo_bin); } void presidency_overlap(t_presidency *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; presidency_init(x,1); } void presidency_winfac(t_presidency *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; presidency_init(x,2); } void presidency_fftinfo(t_presidency *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, winfac %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void presidency_verbose(t_presidency *x, t_floatarg t) { x->verbose = t; } void presidency_size(t_presidency *x, t_floatarg newsize) { //protect with DACs off? if(newsize > 0.0){//could be horrendous size, but that's the user's problem x->duration = newsize/1000.0; presidency_init(x,1); } } void presidency_playthrough (t_presidency *x, t_floatarg tog) { x->playthrough = tog; } void presidency_free(t_presidency *x){ int i ; #if MSP dsp_free((t_pxobject *)x); #endif for(i = 0; i < x->framecount; i++){ freebytes(x->loveboat[i],0) ; } freebytes(x->loveboat,0); freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->local_frame,0); } void presidency_init(t_presidency *x, short initialized) { int i; long oldsize,newsize; int oldN = x->N; int oldN2 = x->N2; int oldNw = x->Nw; int last_framecount = x->framecount; x->lock = 1; x->virgin = 1; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!x->R) x->R = 44100; if(!x->D){ x->D = 256; x->vector_size = x->D; } x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N, &x->Nw, OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; // post("mult %f N %d",x->mult,x->N); x->current_frame = 0; x->fpos = x->last_fpos = 0; x->tadv = (float)x->D/(float)x->R; x->c_fundamental = (float)x->R/((x->N2)<<1); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float)x->D / (float)x->R; x->table_length = 8192; x->table_si = (float) x->table_length / (float) x->R; x->pitch_increment = 1.0 * x->table_si; if( x->duration <= 0 ){ x->duration = 1.0; } x->framecount = x->duration / x->tadv ; x->hopsize = (float)x->N / x->overlap; x->read_me = 0; if(!initialized){ x->mute = 0; x->in2_connected = 0; x->in3_connected = 0; x->sync = 0; x->playthrough = 0; x->frame_increment = 1.0; x->verbose = 0; x->table = (float *) getbytes(x->table_length * sizeof(float)); x->Wanal = (float *) getbytes(MAX_Nw*sizeof(float)); x->Wsyn = (float *) getbytes(MAX_Nw*sizeof(float)); x->input = (float *) getbytes(MAX_Nw*sizeof(float)); x->Hwin = (float *) getbytes(MAX_Nw*sizeof(float)); x->bindex = (float *) getbytes( (MAX_N+1) * sizeof(float) ); x->buffer = (float *) getbytes(MAX_N*sizeof(float)); x->channel = (float *) getbytes((MAX_N+2)*sizeof(float)); x->output = (float *) getbytes(MAX_Nw*sizeof(float)); x->bitshuffle = (int *) getbytes((MAX_N*2)*sizeof(int)); x->trigland = (float *) getbytes((MAX_N*2)*sizeof(float)); x->c_lastphase_in = (float *) getbytes((MAX_N2+1)*sizeof(float)); x->c_lastphase_out = (float *) getbytes((MAX_N2+1)*sizeof(float)); x->lastamp = (float *) getbytes((MAX_N+1) * sizeof(float)); x->lastfreq = (float *) getbytes((MAX_N+1) * sizeof(float)); x->local_frame = (float *) getbytes((MAX_N+2)*sizeof(float)); x->loveboat = (float **) getbytes(x->framecount*sizeof(float *)); /* here we stay with old reallocation approach and pray */ for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes(((x->N)+2)*sizeof(float)); if(x->loveboat[i] == NULL){ error("memory error"); return; } memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float)); } } else if(initialized == 1) { //free and allocate oldsize = (oldN+2)*sizeof(float); for(i = 0; i < last_framecount; i++){ freebytes(x->loveboat[i],oldsize) ; } oldsize = last_framecount*sizeof(float *); freebytes(x->loveboat,oldsize); x->loveboat = (float **) getbytes(x->framecount*sizeof(float *)); for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes((x->N+2)*sizeof(float)); if(x->loveboat[i] == NULL){ error("memory error"); return; } memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float)); } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->lastamp,0,(x->N+1)*sizeof(float)); memset((char *)x->lastfreq,0,(x->N+1)*sizeof(float)); memset((char *)x->bindex,0,(x->N+1)*sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); if(!x->vector_size){ post("zero vector size - something is really screwed up here!"); return; } for ( i = 0; i < x->table_length; i++ ) { x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->table_length); } x->c_fundamental = (float) x->R/(float)x->N ; x->c_factor_in = (float) x->R/((float)x->vector_size * TWOPI); if( x->hi_freq < x->c_fundamental ) { x->hi_freq = x->topfreq ; } x->hi_bin = 1; x->curfreq = 0; while( x->curfreq < x->hi_freq ) { ++(x->hi_bin); x->curfreq += x->c_fundamental ; } x->lo_bin = 0; x->curfreq = 0; while( x->curfreq < x->lo_freq ) { ++(x->lo_bin); x->curfreq += x->c_fundamental ; } if( x->hi_bin > x->N2) x->hi_bin = x->N2 ; if(x->lo_bin > x->hi_bin) x->lo_bin = x->hi_bin; x->i_vector_size = 1.0/x->vector_size; x->pitch_increment = x->P*x->table_length/x->R; makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); init_rdft( x->N, x->bitshuffle, x->trigland); x->lock = 0; } void *presidency_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_presidency *x = (t_presidency *)newobject(presidency_class); dsp_setup((t_pxobject *)x,4); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_presidency *x = (t_presidency *)pd_new(presidency_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->duration = atom_getfloatarg(0,argc,argv)/1000.0; x->lo_freq = atom_getfloatarg(1,argc,argv); x->hi_freq = atom_getfloatarg(2,argc,argv); x->overlap = atom_getfloatarg(3,argc,argv); x->winfac = atom_getfloatarg(4,argc,argv); x->D = sys_getblksize(); x->R = sys_getsr(); x->vector_size = x->D; x->topfreq = 3000.; // default top freq if(!x->lo_freq){ x->lo_freq = 0; } if(!x->hi_freq) x->hi_freq = 4000.0; presidency_init(x,0); return (x); } t_int *presidency_perform(t_int *w) { int i, j; float sample; ////////////////////////////////////////////// t_presidency *x = (t_presidency *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *speed = (t_float *)(w[3]); t_float *position = (t_float *)(w[4]); t_float *pinc = (t_float *)(w[5]); t_float *out = (t_float *)(w[6]); t_float *sync_vec = (t_float *)(w[7]); t_int n = w[8]; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int vector_size = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float *local_frame = x->local_frame; float fframe = x->current_frame ; float last_fpos = x->last_fpos ; int framecount = x->framecount; float fincr = x->frame_increment; float fpos = x->fpos; float pitch_increment = x->pitch_increment; float mult = x->mult; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; float table_si = x->table_si; int lo_bin = x->lo_bin; int hi_bin = x->hi_bin; float i_vector_size = x->i_vector_size; float synthesis_threshold = x->synthesis_threshold; float *lastfreq = x->lastfreq; float *lastamp = x->lastamp; float *bindex = x->bindex; float *table = x->table; int table_length = x->table_length; float sync = x->sync; if(x->lock || x->mute){ while(n--){ *out++ = 0.0; *sync_vec++ = sync; } return (w+9); } #if MSP if (x->in2_connected) { fincr = *speed; } if (x->in3_connected) { fpos = *position; } if (x->in4_connected) { pitch_increment = *pinc * table_si; } #endif #if PD fincr = *speed; fpos = *position; pitch_increment = *pinc * table_si; #endif inCount += D; if(x->read_me) { for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for (j = Nw - D; j < Nw; j++) { input[j] = *in++; } if( x->playthrough ){ for ( j = N-D; j < N; j++ ) { *out++ = input[j] * 0.5; } } else { for ( j = 0; j < D; j++ ){ *out++ = 0.0; } } fold(input, Wanal, Nw, buffer, N, inCount); rdft(N, 1, buffer, bitshuffle, trigland); sync = (float) x->frames_read / (float) framecount; if(x->frames_read >= framecount){ sync = 1.0; x->read_me = 0; if(x->verbose){ post("presidency: data acquisition completed"); } } else { convert(buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in); } x->virgin = 0; for ( j = 0; j < D; j++ ){ *sync_vec++ = sync; } } else if(x->playthrough && x->virgin){ while(n--){ sample = *in++ * 0.5; *out++ = sample; *sync_vec++ = sync; } } /* synthesis section */ else { if(fpos < 0) fpos = 0; if(fpos > 1) fpos = 1; if(fpos != last_fpos){ fframe = fpos * (float) framecount; last_fpos = fpos; } fframe += fincr; while(fframe >= framecount) { fframe -= framecount; } while( fframe < 0. ) { fframe += framecount ; } // copy stored frame to local for possible modifications for(i = 0; i < N; i++){ local_frame[i] = x->loveboat[(int) fframe ][i]; } for( i = lo_bin * 2 + 1; i < hi_bin * 2 + 1; i += 2 ){ local_frame[i] *= pitch_increment; } bloscbank(local_frame, output, D, i_vector_size, lastfreq, lastamp, bindex, table, table_length, synthesis_threshold, lo_bin, hi_bin); for ( j = 0; j < D; j++ ){ *out++ = output[j] * mult; *sync_vec++ = sync; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } } /* restore state variables */ x->inCount = inCount % Nw; x->current_frame = fframe; x->frame_increment = fincr; x->fpos = fpos; x->last_fpos = last_fpos; x->pitch_increment = pitch_increment; x->sync = sync; return (w+9); } #if MSP void presidency_int(t_presidency *x, long i) { presidency_float(x,(float)i); } void presidency_float(t_presidency *x, double f) // Look at floats at inlets { int inlet = ((t_pxobject*)x)->z_in; if (inlet == 1) { x->frame_increment = f; } else if (inlet == 2){ if (f < 0 ){ f = 0; } else if(f > 1) { f = 1.; } x->fpos = f; } else if( inlet == 3 ){ x->pitch_increment = f * x->table_si; } } #endif void presidency_acquire_sample(t_presidency *x) { x->read_me = 1; x->frames_read = 0; if(x->verbose) post("%: beginning spectral data acquisition",OBJECT_NAME); } void presidency_bangname (t_presidency *x) { x->read_me = 1; x->frames_read = 0; if(x->verbose) post("%s: beginning spectral data acquisition",OBJECT_NAME); } void presidency_mute(t_presidency *x, t_floatarg tog) { x->mute = (short)tog; } void presidency_dsp(t_presidency *x, t_signal **sp, short *count) { #if MSP x->in2_connected = count[1]; x->in3_connected = count[2]; x->in4_connected = count[3]; #endif if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; x->vector_size = x->D; if(x->verbose) post("new vsize: %d, new SR:%d",x->D,x->R); presidency_init(x,1); } dsp_add(presidency_perform, 8, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[0]->s_n); } void presidency_assist(t_presidency *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Frame Increment"); break; case 2: sprintf(dst,"(signal/float) Frame Position [0-1]"); break; case 3: sprintf(dst,"(signal/float) Transposition Factor"); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"(signal) Output"); break; case 1: sprintf(dst,"(signal/float) Record Sync"); break; } } } fftease-2.5.2.git20121005/pvcompand~-help.pd0000644000076500007650000000504412067450034016654 0ustar hanshans#N canvas 854 454 487 362 10; #N canvas 0 22 458 308 pvcompand-block 0; #X obj 231 190 block~ 256; #X obj 231 133 pvcompand~; #X obj 231 86 inlet~; #X obj 296 94 inlet; #X obj 362 117 inlet; #X obj 231 159 outlet~; #X connect 1 0 5 0; #X connect 2 0 1 0; #X connect 3 0 1 1; #X connect 4 0 1 0; #X restore 121 99 pd pvcompand-block; #X obj 121 139 dac~; #N canvas 0 22 466 316 messages 0; #X obj 203 227 outlet; #X obj 281 174 fftease-system; #N canvas 181 394 454 304 init 0; #X obj 97 48 loadbang; #X obj 97 182 outlet; #X obj 262 124 s compandslider; #X msg 262 97 -6; #X text 105 152 attempt to preserve overall amplitude; #X msg 97 130 normalize \$1; #X obj 97 103 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X msg 97 83 1; #X connect 0 0 3 0; #X connect 0 0 7 0; #X connect 3 0 2 0; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 6 0; #X restore 203 153 pd init; #X connect 1 0 0 0; #X connect 2 0 0 0; #X restore 242 69 pd messages; #X msg 211 165 \; pd dsp \$1; #X obj 211 143 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X floatatom 181 78 5 0 0 0 - compand-factor -; #X obj 123 229 hsl 128 15 -60 60 0 0 compand-factor compandslider compand-factor -2 -6 0 8 -258842 -1 -1 5115 1; #X text 256 230 -> expansion; #X text 17 230 compression <-; #X text 23 258 pvcompand~ either expands or compresses the differences between the amplitudes of the spectral frames. The threshold is interpreted as dB and useful ranges are from about -60 to +60. Positive values increase the "peakiness" of the sound and negative values tend to whiten the spectrum.; #N canvas 179 221 661 474 sound-source 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array pvcompand-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ pvcompand-sound1; #X msg 31 177 read -resize \$1 pvcompand-sound1; #X connect 2 0 13 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 5 0; #X connect 12 1 7 0; #X connect 13 0 1 0; #X restore 121 38 pd sound-source; #X text 232 39 <- first load sound here; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 2 0 0 2; #X connect 4 0 3 0; #X connect 5 0 0 1; #X connect 10 0 0 0; fftease-2.5.2.git20121005/pvcompand~.c0000644000076500007650000002765412067450034015560 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvcompand_class; #endif #if PD static t_class *pvcompand_class; #endif #define OBJECT_NAME "pvcompand~" #define MAX_N (16384) #define MAX_Nw (MAX_N * 4) typedef struct _pvcompand { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // float mult; float *trigland; int *bitshuffle; // float *curthresh ; float *atten; float *thresh ; int count; float thresh_interval; float max_atten; float atten_interval ; float tstep; float gstep; float last_max_atten; short norml; short mute; short bypass; short connected[2]; int overlap; int winfac; } t_pvcompand; void *pvcompand_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *pvcompand_perform(t_int *w); void pvcompand_dsp(t_pvcompand *x, t_signal **sp, short *count); void pvcompand_assist(t_pvcompand *x, void *b, long m, long a, char *s); void update_thresholds(t_pvcompand *x); void pvcompand_normalize(t_pvcompand *x, t_floatarg val); void pvcompand_float(t_pvcompand *x, double f); void pvcompand_free(t_pvcompand *x); float pvcompand_ampdb(float db); void pvcompand_init(t_pvcompand *x,short initialized); void pvcompand_fftinfo(t_pvcompand *x); void pvcompand_overlap(t_pvcompand *x, t_floatarg f); void pvcompand_winfac(t_pvcompand *x, t_floatarg f); void pvcompand_bypass(t_pvcompand *x, t_floatarg f); void pvcompand_mute(t_pvcompand *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&pvcompand_class, (method)pvcompand_new, (method)pvcompand_free, (short)sizeof(t_pvcompand), 0, A_GIMME, 0); addmess((method)pvcompand_dsp, "dsp", A_CANT, 0); addmess((method)pvcompand_normalize, "normalize", A_LONG, 0); addmess((method)pvcompand_winfac,"winfac", A_FLOAT, 0); addmess((method)pvcompand_overlap,"overlap", A_FLOAT, 0); addmess((method)pvcompand_fftinfo,"fftinfo", 0); addmess((method)pvcompand_bypass,"bypass", A_FLOAT, 0); addmess((method)pvcompand_mute,"mute", A_FLOAT, 0); addmess((method)pvcompand_assist,"assist",A_CANT,0); addfloat((method)pvcompand_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void pvcompand_tilde_setup(void) { pvcompand_class = class_new(gensym("pvcompand~"), (t_newmethod)pvcompand_new, (t_method)pvcompand_free ,sizeof(t_pvcompand), 0,A_GIMME,0); CLASS_MAINSIGNALIN(pvcompand_class, t_pvcompand, x_f); class_addmethod(pvcompand_class,(t_method)pvcompand_dsp,gensym("dsp"),0); class_addmethod(pvcompand_class,(t_method)pvcompand_mute,gensym("mute"),A_FLOAT,0); class_addmethod(pvcompand_class,(t_method)pvcompand_bypass,gensym("bypass"),A_FLOAT,0); class_addmethod(pvcompand_class,(t_method)pvcompand_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(pvcompand_class,(t_method)pvcompand_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(pvcompand_class,(t_method)pvcompand_fftinfo,gensym("fftinfo"),0); class_addmethod(pvcompand_class,(t_method)pvcompand_normalize,gensym("normalize"),A_FLOAT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void pvcompand_bypass(t_pvcompand *x, t_floatarg f) { x->bypass = (short)f; } void pvcompand_mute(t_pvcompand *x, t_floatarg f) { x->mute = (short)f; } void pvcompand_free( t_pvcompand *x ){ #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->curthresh,0); freebytes(x->atten,0); freebytes(x->thresh,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); } void pvcompand_assist (t_pvcompand *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(float/signal) Threshold"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } #if MSP void pvcompand_float(t_pvcompand *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->last_max_atten = x->max_atten = f; update_thresholds(x); } } #endif void *pvcompand_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_pvcompand *x = (t_pvcompand *)newobject(pvcompand_class); dsp_setup((t_pxobject *)x,2); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_pvcompand *x = (t_pvcompand *)pd_new(pvcompand_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif // INITIALIZATIONS x->D = sys_getblksize(); x->R = sys_getsr(); x->max_atten = atom_getfloatarg(0,argc,argv); x->overlap = atom_getfloatarg(1,argc,argv); x->winfac = atom_getfloatarg(2,argc,argv); if(!x->max_atten) x->max_atten = -6; if(x->D <= 0) x->D = 256; if(x->R <= 0) x->R = 44100; pvcompand_init(x,0); return (x); } void pvcompand_init(t_pvcompand *x,short initialized) { int i; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->norml = 0; x->mute = 0; x->bypass = 0; x->thresh_interval = 1.0; x->last_max_atten = x->max_atten; x->atten_interval = 2.0 ; x->tstep = 1.0 ; x->gstep = 2.0 ; x->Wanal = (float *) getbytes(MAX_Nw * sizeof(float)); x->Wsyn = (float *) getbytes(MAX_Nw * sizeof(float)); x->Hwin = (float *) getbytes(MAX_Nw * sizeof(float)); x->input = (float *) getbytes(MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes(MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes(MAX_N * sizeof(float) ); x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes(MAX_N * 2 * sizeof( float ) ); x->thresh = (float *) getbytes(MAX_N * sizeof(float) ); x->atten = (float *) getbytes(MAX_N * sizeof(float) ); x->curthresh = (float *) getbytes(MAX_N * sizeof(float) ); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); update_thresholds(x); } void update_thresholds( t_pvcompand *x ) { int i; float nowamp = x->max_atten ; float nowthresh = 0.0 ; x->count = 0; if( nowamp < 0.0 ) while( nowamp < 0.0 ){ x->atten[x->count] = pvcompand_ampdb( nowamp ); nowamp += x->gstep ; ++(x->count); if(x->count >= x->N){ error("count exceeds %d",x->N); x->count = x->N - 1; break; } } else if( nowamp > 0.0 ) while( nowamp > 0.0 ){ x->atten[x->count] = pvcompand_ampdb( nowamp ); nowamp -= x->gstep ; ++(x->count); if(x->count >= x->N){ error("count exceeds %d",x->N); x->count = x->N - 1; break; } } for( i = 0; i < x->count; i++){ x->thresh[i] = pvcompand_ampdb( nowthresh ); nowthresh -= x->tstep ; } /* for( i = 0; i < count; i++) fprintf(stderr,"thresh %f gain %f\n",thresh[i], atten[i]); */ } void pvcompand_normalize(t_pvcompand *x, t_floatarg val) { x->norml = val; } t_int *pvcompand_perform(t_int *w) { float sample, outsamp ; int i,j; float maxamp ; float fmult; float cutoff; float avr, new_avr, rescale; t_pvcompand *x = (t_pvcompand *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *out = (t_float *)(w[4]); int n = (int)(w[5]); int inCount = x->inCount; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; int count = x->count; float *atten = x->atten; float *curthresh = x->curthresh; float *thresh = x->thresh; float max_atten = x->max_atten; if( x->mute ){ while( n-- ){ *out++ = 0.0; } return (w+6); } if( x->bypass ){ while( n-- ){ *out++ = *in++ * 0.5; // gain compensation } return (w+6); } #if MSP if( x->connected[1] ){ max_atten = *in2++ ; if(max_atten != x->last_max_atten) { x->last_max_atten = x->max_atten = max_atten; update_thresholds(x); } } #endif #if PD max_atten = *in2++ ; if(max_atten != x->last_max_atten) { x->last_max_atten = x->max_atten = max_atten; update_thresholds(x); } #endif inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); leanconvert(buffer, channel, N2); maxamp = 0.; avr = 0; for( i = 0; i < N; i+= 2 ){ avr += channel[i]; if( maxamp < channel[i] ){ maxamp = channel[i] ; } } if(count <= 1){ // post("count too low!"); count = 1; } for( i = 0; i < count; i++ ){ curthresh[i] = thresh[i]*maxamp ; } cutoff = curthresh[count-1]; new_avr = 0; for( i = 0; i < N; i += 2){ if( channel[i] > cutoff ){ j = count-1; while( channel[i] > curthresh[j] ){ j--; if( j < 0 ){ j = 0; break; } } channel[i] *= atten[j]; } new_avr += channel[i] ; } leanunconvert( channel,buffer, N2); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount); if( x->norml ) { if( new_avr <= 0 ){ new_avr = .0001; } rescale = avr / new_avr ; mult *= rescale ; } else { mult *= pvcompand_ampdb( max_atten * -.5); ; } for ( j = 0; j < D; j++ ){ *out++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+6); } float pvcompand_ampdb(float db) { float amp; amp = pow((double)10.0, (double)(db/20.0)) ; return(amp); } void pvcompand_overlap(t_pvcompand *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; pvcompand_init(x,1); } void pvcompand_winfac(t_pvcompand *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; pvcompand_init(x,2); } void pvcompand_fftinfo(t_pvcompand *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void pvcompand_dsp(t_pvcompand *x, t_signal **sp, short *count) { long i; #if MSP x->connected[1] = count[1]; #endif if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr ){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; pvcompand_init(x,1); } dsp_add(pvcompand_perform, 5,x,sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/pvgrain~-help.pd0000644000076500007650000002270512067452034016340 0ustar hanshans#N canvas 772 607 490 340 10; #N canvas 0 22 482 332 pvgrain-block 0; #X obj 9 110 outlet; #X obj 9 15 inlet~; #X obj 94 15 inlet; #X obj 8 140 block~ 256; #X text 12 90 args: grains/frame \, odds \, topfreq \, overlap \, window-factor ; #X obj 9 68 pvgrain~ 4 0.01 2000 4 2; #X connect 1 0 5 0; #X connect 2 0 5 0; #X connect 5 0 0 0; #X restore 13 103 pd pvgrain-block; #X obj 220 158 dac~; #X obj 13 172 print; #X msg 110 242 \; pd dsp \$1; #X obj 110 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #N canvas 368 141 902 629 messages 0; #X obj 111 523 outlet; #X msg 105 115 probability \$1; #X obj 108 68 hsl 128 15 0 0.1 0 0 empty empty empty -2 -6 0 8 -43542 -1 -1 1270 1; #X floatatom 105 94 5 0 0 0 - - -; #X obj 198 179 hsl 128 15 200 10000 0 0 empty empty empty -2 -6 0 8 -43542 -1 -1 2333 1; #X floatatom 195 205 5 0 0 0 - - -; #X msg 195 226 topfreq \$1; #X obj 439 388 hsl 128 15 0 20 0 0 empty empty empty -2 -6 0 8 -43542 -1 -1 5080 1; #X floatatom 436 414 5 0 0 0 - - -; #X msg 436 435 framegrains \$1; #X obj 105 1 loadbang; #X obj 283 284 hsl 128 15 0 1500 0 0 empty empty empty -2 -6 0 8 -43542 -1 -1 423 1; #X floatatom 280 310 5 0 0 0 - - -; #X msg 280 331 bottomfreq \$1; #X obj 105 40 unpack f f f f; #X msg 105 21 0.01 2000 50 8; #X obj 300 492 fftease-system; #X text 436 363 maximum data grains per FFT frame; #X text 197 157 top frequency to listen to in source sound; #X text 283 263 ditto for bottom frequency; #X text 221 48 odds for a grain appearing from an active bin; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 0 0; #X connect 7 0 8 0; #X connect 8 0 9 0; #X connect 9 0 0 0; #X connect 10 0 15 0; #X connect 11 0 12 0; #X connect 12 0 13 0; #X connect 13 0 0 0; #X connect 14 0 2 0; #X connect 14 1 4 0; #X connect 14 2 11 0; #X connect 14 3 7 0; #X connect 15 0 14 0; #X connect 16 0 0 0; #X restore 120 62 pd messages; #X obj 50 129 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 13 149 spigot; #X text 69 131 see amp/freq info; #X text 42 277 spectral granular (re)synthesis; #N canvas 0 22 478 328 resynth-engine 0; #X obj 12 28 inlet; #N canvas 0 22 450 300 graph1 0; #X array piano-sample 46383 float 2; #X coords 0 1 46382 -1 200 140 1; #X restore 215 4 graph; #X obj 17 242 soundfiler; #X msg 17 205 read -resize examples/Piano.aif piano-sample; #X obj 17 169 loadbang; #N canvas 578 40 566 745 choir 0; #X obj 79 103 inlet; #X obj 79 141 t l b; #X obj 25 199 float; #X obj 25 228 + 1; #X obj 25 252 % 8; #X floatatom 25 276 5 0 0 0 - - -; #X obj 47 367 pack f f f; #X obj 79 315 unpack f f; #X obj 47 395 route 0 1 2 3 4 5 6 7; #X obj 112 343 / 261; #X text 156 345 <- piano sample base frequency; #N canvas 74 88 1066 749 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 47 430 pd playit; #X obj 123 595 outlet~; #X obj 123 572 *~ 0.25; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 64 451 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 83 472 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 101 493 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 118 421 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 135 442 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 154 463 pd playit; #N canvas 74 88 1062 745 playit 0; #X obj 21 47 unpack f f; #X obj 21 222 outlet~; #X floatatom 131 120 5 0 0 0 - - -; #X floatatom 88 118 5 0 0 0 - - -; #X obj 21 119 impulse~; #X obj 21 146 *~; #X obj 21 80 t b f; #X obj 21 182 player~ piano-sample; #X obj 21 8 inlet; #X connect 0 0 6 0; #X connect 0 1 2 0; #X connect 2 0 7 1; #X connect 3 0 5 1; #X connect 4 0 5 0; #X connect 5 0 7 0; #X connect 6 0 4 0; #X connect 6 1 3 0; #X connect 7 0 1 0; #X connect 8 0 0 0; #X restore 172 484 pd playit; #X connect 0 0 1 0; #X connect 1 0 7 0; #X connect 1 1 2 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 4 0 2 1; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 8 0; #X connect 7 0 6 1; #X connect 7 1 9 0; #X connect 8 0 11 0; #X connect 8 1 14 0; #X connect 8 2 15 0; #X connect 8 3 16 0; #X connect 8 4 17 0; #X connect 8 5 18 0; #X connect 8 6 19 0; #X connect 8 7 20 0; #X connect 9 0 6 2; #X connect 11 0 13 0; #X connect 13 0 12 0; #X connect 14 0 13 0; #X connect 15 0 13 0; #X connect 16 0 13 0; #X connect 17 0 13 0; #X connect 18 0 13 0; #X connect 19 0 13 0; #X connect 20 0 13 0; #X restore 12 97 pd choir; #X obj 12 121 outlet~; #X text 13 269 this is one example of what you can do with the analysis data; #X obj 12 63 spigot; #X obj 49 44 inlet; #X obj 113 27 loadbang; #X msg 113 47 0; #X connect 0 0 8 0; #X connect 3 0 2 0; #X connect 4 0 3 0; #X connect 5 0 6 0; #X connect 8 0 5 0; #X connect 9 0 8 1; #X connect 10 0 11 0; #X connect 11 0 8 1; #X restore 220 119 pd resynth-engine; #N canvas 408 408 482 332 sound-source 0; #X obj -34 240 outlet~; #X obj -34 215 *~ 0.3; #X floatatom -34 72 5 0 0 0 - - -; #X obj 149 119 * 1.5; #X floatatom 51 142 5 0 0 0 - - -; #X floatatom 149 143 5 0 0 0 - - -; #X obj 51 161 phasor~ 586.6; #X obj 149 161 phasor~ 660; #X obj -34 161 phasor~ 440; #X obj 51 119 * 1.25; #X msg -34 41 440; #X obj -34 15 loadbang; #X text -18 262 a soundfile or live mic would be more interesting here ; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 2 0 8 0; #X connect 2 0 9 0; #X connect 3 0 5 0; #X connect 4 0 6 0; #X connect 5 0 7 0; #X connect 6 0 1 0; #X connect 7 0 1 0; #X connect 8 0 1 0; #X connect 9 0 4 0; #X connect 10 0 2 0; #X connect 11 0 10 0; #X restore 13 41 pd sound-source; #N canvas 180 51 470 320 what's-going-on-here? 0; #X text 18 26 Input sound is analyzed and a certain number of bin snapshots are taken \, based on the probability and framegrains parameters. Each bin grain snapshot is sent out as a list with two members: [amplitude \, frequency]. In this example the grain data is used to drive a sample player. One could easily replace this with a synth or even drive an external MIDI synth. This is something like a pitch-follower except that it follows the entire spectrum (limited by the topfreq parameter) rather than just looking for the fundamental. Since this is based on FFT analysis the resolution is worse for lower frequencies. Frequency resolution can be improved by upping the FFT size.; #X restore 269 203 pd what's-going-on-here?; #X obj 334 96 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X text 356 98 <- turn me on; #X text 204 64 <- check me out; #X connect 0 0 7 0; #X connect 0 0 10 0; #X connect 4 0 3 0; #X connect 5 0 0 1; #X connect 6 0 7 1; #X connect 7 0 2 0; #X connect 10 0 1 0; #X connect 10 0 1 1; #X connect 11 0 0 0; #X connect 13 0 10 1; fftease-2.5.2.git20121005/pvgrain~.c0000644000076500007650000003307512067450034015231 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvgrain_class; #endif #if PD static t_class *pvgrain_class; #endif #define OBJECT_NAME "pvgrain~" typedef struct _pvgrain { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // for convert float *c_lastphase_in; float c_fundamental; float c_factor_in; float c_factor_out; float synt; // for oscbank int NP; float P; int L; int first; float Iinv; float *lastamp; float *lastfreq; float *index; float *table; short *binsort; float myPInc; float ffac; // int lo_bin; int hi_bin; float topfreq; float bottomfreq; // for fast fft float mult; float *trigland; int *bitshuffle; // int mute; float grain_probability; float sample_basefreq; int grains_per_frame ; void *list_outlet; float *listdata; short list_count; void *m_clock; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_pvgrain; void *pvgrain_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *pvgrain_perform(t_int *w); void pvgrain_dsp(t_pvgrain *x, t_signal **sp, short *count); void pvgrain_assist(t_pvgrain *x, void *b, long m, long a, char *s); void pvgrain_mute(t_pvgrain *x, t_floatarg state); void pvgrain_float(t_pvgrain *x, double f); void pvgrain_tick(t_pvgrain *x); void pvgrain_printchan(t_pvgrain *x); void pvgrain_probability (t_pvgrain *x, t_floatarg prob); void pvgrain_framegrains (t_pvgrain *x, t_floatarg grains); void pvgrain_topfreq (t_pvgrain *x, t_floatarg top); void pvgrain_bottomfreq (t_pvgrain *x, t_floatarg f); void pvgrain_basefreq (t_pvgrain *x, t_floatarg base); float pvgrain_randf(float min, float max); void pvgrain_init(t_pvgrain *x, short initialized); void pvgrain_free(t_pvgrain *x); void pvgrain_winfac(t_pvgrain *x, t_floatarg factor); void pvgrain_overlap(t_pvgrain *x, t_floatarg o); void pvgrain_fftinfo(t_pvgrain *x) ; #if MSP void main(void) { setup((t_messlist **)&pvgrain_class, (method)pvgrain_new, (method)pvgrain_free, (short)sizeof(t_pvgrain), 0, A_GIMME, 0); addmess((method)pvgrain_dsp, "dsp", A_CANT, 0); addmess((method)pvgrain_assist,"assist",A_CANT,0); addmess((method)pvgrain_mute,"mute",A_DEFFLOAT,0); addmess((method)pvgrain_printchan,"printchan",A_DEFFLOAT,0); addmess((method)pvgrain_probability,"probability",A_DEFFLOAT,0); addmess((method)pvgrain_framegrains,"framegrains",A_DEFFLOAT,0); addmess((method)pvgrain_topfreq,"topfreq",A_DEFFLOAT,0); addmess((method)pvgrain_basefreq,"basefreq",A_DEFFLOAT,0); addmess((method)pvgrain_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)pvgrain_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)pvgrain_fftinfo, "fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT);} #endif #if PD void pvgrain_tilde_setup(void) { pvgrain_class = class_new(gensym("pvgrain~"), (t_newmethod)pvgrain_new, (t_method)pvgrain_free ,sizeof(t_pvgrain), 0, A_GIMME, 0); CLASS_MAINSIGNALIN(pvgrain_class, t_pvgrain, x_f); class_addmethod(pvgrain_class, (t_method)pvgrain_dsp, gensym("dsp"), 0); class_addmethod(pvgrain_class, (t_method)pvgrain_mute, gensym("mute"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_topfreq, gensym("topfreq"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_bottomfreq, gensym("bottomfreq"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_printchan, gensym("printchan"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_probability, gensym("probability"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_framegrains, gensym("framegrains"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_basefreq, gensym("basefreq"), A_FLOAT, 0); class_addmethod(pvgrain_class, (t_method)pvgrain_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(pvgrain_class, (t_method)pvgrain_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(pvgrain_class, (t_method)pvgrain_fftinfo, gensym("fftinfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void pvgrain_printchan(t_pvgrain *x) { int i; post("***"); for( i = 0 ; i < 30; i+= 2 ){ post("amp %f freq %f", x->channel[i*2], x->channel[i*2 + 1]); } post("***"); } void pvgrain_basefreq (t_pvgrain *x, t_floatarg base) { if( base < 0.0 ) base = 0. ; if( base > x->R / 2 ) base = x->R / 2 ; x->sample_basefreq = base; } void pvgrain_topfreq (t_pvgrain *x, t_floatarg top) { float curfreq ; if( top < 50. ) top = 50.; if( top > x->R / 2 ) top = x->R / 2; x->topfreq = top ; curfreq = 0; x->hi_bin = 0; while( curfreq < x->topfreq ) { ++(x->hi_bin); curfreq += x->c_fundamental ; } } void pvgrain_bottomfreq (t_pvgrain *x, t_floatarg f) { float curfreq; if( f >= x->topfreq || f >= x->R/2){ post("%f is too high a bottom freq",f); return; } x->bottomfreq = f; curfreq = 0; x->lo_bin = 0; while( curfreq < x->bottomfreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } // post("low bin: %d high bin: %d",x->lo_bin,x->hi_bin); } void pvgrain_probability (t_pvgrain *x, t_floatarg prob) { if( prob < 0. ) prob = 0.; if( prob > 1. ) prob = 1.; x->grain_probability = prob ; } void pvgrain_framegrains (t_pvgrain *x, t_floatarg grains) { if( grains < 1 ) grains = 1; if( grains > x->N2 - 1 ) grains = x->N2 - 1; x->grains_per_frame = grains ; } void pvgrain_tick(t_pvgrain *x) { t_atom myList[2]; float *listdata = x->listdata; int i; for (i=0; i < 2; i++) { SETFLOAT(myList+i,listdata[i]); /* macro for setting a t_atom */ } outlet_list(x->list_outlet,0L,2,myList); } void pvgrain_assist (t_pvgrain *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; } } else if (msg==2) { sprintf(dst,"(list) Amplitude/Frequency Pairs"); } } void *pvgrain_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_pvgrain *x = (t_pvgrain *)newobject(pvgrain_class); dsp_setup((t_pxobject *)x,1); x->list_outlet = listout(x); #endif #if PD t_pvgrain *x = (t_pvgrain *)pd_new(pvgrain_class); x->list_outlet = outlet_new(&x->x_obj,gensym("list")); #endif x->vs = sys_getblksize(); x->R = sys_getsr(); x->grains_per_frame = atom_getfloatarg(0,argc,argv); x->grain_probability = atom_getfloatarg(1,argc,argv); x->topfreq = atom_getfloatarg(2,argc,argv); x->overlap = atom_getfloatarg(3,argc,argv); x->winfac = atom_getfloatarg(4,argc,argv); if(!x->grains_per_frame) x->grains_per_frame = 4; if(!x->grain_probability) x->grain_probability = .0001; if(!x->topfreq) x->topfreq = 1000; if(!x->overlap) x->overlap = 2; if(!x->winfac) x->winfac = 4; pvgrain_init(x,0); return (x); } void pvgrain_init(t_pvgrain *x, short initialized) { float curfreq; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->Iinv = 1./x->D; x->myPInc = x->P*x->L/x->R; x->ffac = x->P * PI/x->N; #if MSP x->m_clock = clock_new(x,(method)pvgrain_tick); #endif #if PD x->m_clock = clock_new(x,(void *)pvgrain_tick); #endif x->c_fundamental = (float) x->R/(float)( (x->N2)<<1); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->P = 1.0 ; x->sample_basefreq = 261.0; x->bottomfreq = 0.0; x->mute = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->binsort = (short *) getbytes((MAX_N2+1) * sizeof(short) ); x->listdata = (float *) getbytes(40 * sizeof(float)); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); curfreq = 0; x->hi_bin = 0; x->lo_bin = 0; while( curfreq < x->topfreq ) { ++(x->hi_bin); curfreq += x->c_fundamental ; } x->lo_bin = 0; curfreq = 0; while( curfreq < x->bottomfreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } } void pvgrain_overlap(t_pvgrain *x, t_floatarg o) { if(!fftease_power_of_two((int)o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; pvgrain_init(x,1); } void pvgrain_winfac(t_pvgrain *x, t_floatarg f) { if(!fftease_power_of_two((int)f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; pvgrain_init(x,2); } void pvgrain_fftinfo( t_pvgrain *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void pvgrain_free(t_pvgrain *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->c_lastphase_in,0); freebytes(x->binsort,0); freebytes(x->listdata,0); } t_int *pvgrain_perform(t_int *w) { int i,j, in; float tmp, dice; short print_grain; t_pvgrain *x = (t_pvgrain *) (w[1]); t_float *inbuf = (t_float *)(w[2]); t_int n = w[3]; short *binsort = x->binsort; int grains_per_frame = x->grains_per_frame ; int hi_bin = x->hi_bin; int lo_bin = x->lo_bin; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float factor_in = x->c_factor_in; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float fundamental = x->c_fundamental; float *lastphase_in = x->c_lastphase_in; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float selection_probability = x->grain_probability; if (x->mute) { return (w+4); } in = x->inCount ; x->list_count = 0; in += D; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *inbuf++; } fold( input, Wanal, Nw, buffer, N, in ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, lastphase_in, fundamental, factor_in ); if( grains_per_frame > hi_bin - lo_bin ) grains_per_frame = hi_bin - lo_bin; // binsort[0] = 0; for( i = 0; i < hi_bin; i++ ){// could be hi_bin - lo_bin binsort[i] = i + lo_bin; } for( i = lo_bin; i < hi_bin - 1; i++ ){ for( j = i+1; j < hi_bin; j++ ){ if(channel[binsort[j] * 2] > channel[binsort[i] * 2]) { tmp = binsort[j]; binsort[j] = binsort[i]; binsort[i] = tmp; } } } for( i = 0; i < grains_per_frame; i++ ){ print_grain = 1; dice = pvgrain_randf(0.,1.); if( dice < 0.0 || dice > 1.0 ){ error("dice %f out of range", dice); } if( selection_probability < 1.0 ){ if( dice > selection_probability) { print_grain = 0; } } if( print_grain ){ x->listdata[ x->list_count * 2 ] = channel[ binsort[i]*2 ]; x->listdata[ (x->list_count * 2) + 1 ] = channel[(binsort[i]*2) + 1] ; ++(x->list_count); clock_delay(x->m_clock,0); } } x->inCount = in % Nw; return (w+4); } float pvgrain_randf(float min, float max) { float guess; guess = (float) (rand() % RAND_MAX) / (float) RAND_MAX ; return ( min + guess * (max - min) ); } void pvgrain_mute(t_pvgrain *x, t_floatarg state) { x->mute = (short)state; } #if MSP void pvgrain_float(t_pvgrain *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->P = f; //post("P set to %f",f); } else if (inlet == 2) { x->synt = f; //post("synt set to %f",f); } } #endif void pvgrain_dsp(t_pvgrain *x, t_signal **sp, short *count) { /* long i; if( count[1] ){ x->pitch_connected = 1; } else { x->pitch_connected = 0; } if( count[2] ){ x->synt_connected = 1; } else { x->synt_connected = 0; } */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; pvgrain_init(x,1); } dsp_add(pvgrain_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/pvharm~-help.pd0000644000076500007650000000454012067450034016162 0ustar hanshans#N canvas 768 40 466 316 10; #N canvas 0 22 466 316 pvharm-block 0; #X obj 22 81 pvharm~ 0 3000 4 1; #X obj 22 130 outlet~; #X obj 22 20 inlet~; #X obj 22 156 block~ 256; #X obj 62 41 inlet; #X obj 102 41 inlet; #X obj 143 41 inlet; #X obj 216 65 inlet; #X text 32 106 args: lowfreq \, highfreq \, overlap \, window-factor ; #X connect 0 0 1 0; #X connect 2 0 0 0; #X connect 4 0 0 1; #X connect 5 0 0 2; #X connect 6 0 0 3; #X connect 7 0 0 0; #X restore 70 134 pd pvharm-block; #X obj 70 200 dac~; #X obj 70 177 *~ 0.1; #X obj 70 53 phasor~ 300; #X floatatom 95 80 5 0 0 1 transpose1 - -; #X floatatom 120 97 5 0 0 1 transpose2 - -; #X floatatom 145 114 5 0 0 1 synth-threshold - -; #N canvas 587 239 474 324 messages 0; #X obj 61 259 outlet; #X msg 61 121 highfreq \$1; #X floatatom 61 100 5 0 0 0 - - -; #X floatatom 118 168 5 0 0 0 - - -; #X msg 118 189 lowfreq \$1; #X obj 165 228 fftease-system; #X obj 64 72 hsl 128 15 500 5000 0 0 empty empty empty -2 -6 0 8 -184257 -1 -1 3500 1; #X obj 121 144 hsl 128 15 0 450 0 0 empty empty empty -2 -6 0 8 -184257 -1 -1 5700 1; #X text 29 37 synthesis frequency boundaries; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 2 0; #X connect 7 0 3 0; #X restore 292 118 pd messages; #X obj 13 136 *~ 0.3; #X msg 163 206 \; pd dsp \$1; #X obj 110 155 hsl 128 15 0 0.2 0 0 empty empty empty -2 -6 0 8 -184257 -1 -1 3500 1; #X obj 163 180 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X floatatom 70 30 5 0 0 0 - - -; #X text 18 254 pvharm~ provides basic harmonizing with two transpositions of the input internally calculated and mixed to the output; #N canvas 578 326 1043 702 init 0; #X obj 56 175 outlet; #X obj 104 171 outlet; #X obj 157 173 outlet; #X obj 230 177 outlet; #X obj 179 21 loadbang; #X msg 179 43 165 1.25 1.5 0.01; #X obj 179 64 unpack f f f f; #X connect 4 0 5 0; #X connect 5 0 6 0; #X connect 6 0 0 0; #X connect 6 1 1 0; #X connect 6 2 2 0; #X connect 6 3 3 0; #X restore 369 -6 pd init; #X text 244 156 gain; #X connect 0 0 2 0; #X connect 2 0 1 0; #X connect 2 0 1 1; #X connect 3 0 0 0; #X connect 3 0 8 0; #X connect 4 0 0 1; #X connect 5 0 0 2; #X connect 6 0 0 3; #X connect 7 0 0 4; #X connect 8 0 2 0; #X connect 10 0 2 1; #X connect 11 0 9 0; #X connect 12 0 3 0; #X connect 14 0 12 0; #X connect 14 1 4 0; #X connect 14 2 5 0; #X connect 14 3 6 0; fftease-2.5.2.git20121005/pvharm~.c0000644000076500007650000003445112067450034015057 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvharm_class; #endif #if PD static t_class *pvharm_class; #endif #define OBJECT_NAME "pvharm~" typedef struct _pvharm { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // for convert float *c_lastphase_in; // float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; float *table; int NP; int L; int first; float Iinv; float ffac; // for oscbank 1 float *lastamp; float *lastfreq; float *index; int lo_bin; int hi_bin; float topfreq; float P; float myPInc; // // for oscbank 2 float *lastamp2; float *lastfreq2; float *index2; int lo_bin2; int hi_bin2; float topfreq2; float P2; float myPInc2; // float synt; float myPI; float TWOmyPI; // for fast fft float mult; float *trigland; int *bitshuffle; short pitch1_connected; short pitch2_connected; short synt_connected; short mute; int vs;//vector size int overlap;//overlap factor int winfac;//window size factor float hifreq;//highest frequency to synthesize float lofreq;//lowest frequency to synthesize } t_pvharm; void *pvharm_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *pvharm_perform(t_int *w); void pvharm_dsp(t_pvharm *x, t_signal **sp, short *count); void pvharm_assist(t_pvharm *x, void *b, long m, long a, char *s); void pvharm_float(t_pvharm *x, double f); void pvharm_mute(t_pvharm *x, t_floatarg f); void pvharm_init(t_pvharm *x, short initialized); void pvharm_lowfreq(t_pvharm *x, t_floatarg f); void pvharm_highfreq(t_pvharm *x, t_floatarg f); void pvharm_free(t_pvharm *x); void pvharm_fftinfo(t_pvharm *x); void pvharm_overlap(t_pvharm *x, t_floatarg f); void pvharm_winfac(t_pvharm *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **) &pvharm_class, (method) pvharm_new, (method)pvharm_free, (short)sizeof(t_pvharm), 0, A_GIMME, 0); addmess((method)pvharm_dsp, "dsp", A_CANT, 0); addmess((method)pvharm_assist,"assist",A_CANT,0); addmess((method)pvharm_mute,"mute",A_DEFFLOAT,0); addmess((method)pvharm_lowfreq,"lowfreq",A_FLOAT,0); addmess((method)pvharm_highfreq,"highfreq",A_FLOAT,0); addmess((method)pvharm_overlap,"overlap",A_DEFFLOAT,0); addmess((method)pvharm_winfac,"winfac",A_DEFFLOAT,0); addmess((method)pvharm_fftinfo,"fftinfo",0); addfloat((method)pvharm_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void pvharm_tilde_setup(void) { pvharm_class = class_new(gensym("pvharm~"), (t_newmethod)pvharm_new, (t_method)pvharm_free ,sizeof(t_pvharm), 0,A_GIMME,0); CLASS_MAINSIGNALIN(pvharm_class, t_pvharm, x_f); class_addmethod(pvharm_class, (t_method)pvharm_dsp, gensym("dsp"), 0); class_addmethod(pvharm_class, (t_method)pvharm_assist, gensym("assist"), 0); class_addmethod(pvharm_class, (t_method)pvharm_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(pvharm_class, (t_method)pvharm_highfreq, gensym("highfreq"), A_DEFFLOAT,0); class_addmethod(pvharm_class, (t_method)pvharm_lowfreq, gensym("lowfreq"), A_DEFFLOAT,0); class_addmethod(pvharm_class,(t_method)pvharm_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(pvharm_class,(t_method)pvharm_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(pvharm_class,(t_method)pvharm_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void pvharm_free(t_pvharm *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->c_lastphase_in,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->lastamp,0); freebytes(x->lastamp2,0); freebytes(x->lastfreq,0); freebytes(x->lastfreq2,0); freebytes(x->index,0); freebytes(x->index2,0); freebytes(x->table,0); } void pvharm_assist (t_pvharm *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Pitch Multiplier 1"); break; case 2: sprintf(dst,"(signal/float) Pitch Multiplier 2"); break; case 3: sprintf(dst,"(signal/float) Synthesis Threshold"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void pvharm_overlap(t_pvharm *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; pvharm_init(x,1); } void pvharm_winfac(t_pvharm *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; pvharm_init(x,2); } void pvharm_fftinfo(t_pvharm *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void pvharm_highfreq(t_pvharm *x, t_floatarg f) { float curfreq; if(f < x->lofreq){ error("current minimum is %f",x->lofreq); return; } if(f > x->R/2 ){ f = x->R/2; } x->hifreq = f; x->hi_bin = 1; curfreq = 0; while(curfreq < x->hifreq) { ++(x->hi_bin); curfreq += x->c_fundamental; } } void pvharm_lowfreq(t_pvharm *x, t_floatarg f) { float curfreq; if(f > x->hifreq){ error("current maximum is %f",x->lofreq); return; } if(f < 0 ){ f = 0; } x->lofreq = f; x->lo_bin = 0; curfreq = 0; while( curfreq < x->lofreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } } void *pvharm_new(t_symbol *s, int argc, t_atom *argv) { // int i; #if MSP t_pvharm *x = (t_pvharm *)newobject(pvharm_class); dsp_setup((t_pxobject *)x,4); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_pvharm *x = (t_pvharm *)pd_new(pvharm_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->vs = sys_getblksize(); x->R = sys_getsr(); x->lofreq = atom_getfloatarg(0,argc,argv); x->hifreq = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(x->lofreq <0 || x->lofreq> 22050) x->lofreq = 0; if(x->hifreq <50 || x->hifreq> 22050) x->hifreq = 4000; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 2; pvharm_init(x,0); return (x); } void pvharm_init(t_pvharm *x, short initialized) { int i; float curfreq; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->Iinv = 1./x->D; x->c_fundamental = (float) x->R/(float)((x->N2)<<1); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->P = .5 ; // for testing purposes x->P2 = .6666666666 ; // for testing purposes x->L = 8192 ; x->synt = .00005; x->mute = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->lastamp = (float *) getbytes((MAX_N+1) * sizeof(float)); x->lastfreq = (float *) getbytes((MAX_N+1) * sizeof(float)); x->lastamp2 = (float *) getbytes((MAX_N+1) * sizeof(float)); x->lastfreq2 = (float *) getbytes((MAX_N+1) * sizeof(float)); x->index = (float *) getbytes((MAX_N+1) * sizeof(float)); x->index2 = (float *) getbytes((MAX_N+1) * sizeof(float)); x->table = (float *) getbytes(x->L * sizeof(float)); x->c_lastphase_in = (float *) getbytes((MAX_N2+1) * sizeof(float)); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->lastamp,0,(x->N+1) * sizeof(float)); memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float)); memset((char *)x->lastamp2,0,(x->N+1) * sizeof(float)); memset((char *)x->lastfreq2,0,(x->N+1) * sizeof(float)); memset((char *)x->index,0,(x->N+1) * sizeof(float)); memset((char *)x->index2,0,(x->N+1) * sizeof(float)); x->myPInc = x->P * x->L/x->R; x->myPInc2 = x->P2 * x->L/x->R; x->ffac = x->P * PI/x->N; if(x->hifreq < x->c_fundamental) { x->hifreq = 3000.0 ; } x->hi_bin = 1; curfreq = 0; while(curfreq < x->hifreq) { ++(x->hi_bin); curfreq += x->c_fundamental ; } if( x->hi_bin >= x->N2 ){ x->hi_bin = x->N2 - 1; } x->lo_bin = 0; curfreq = 0; while(curfreq < x->lofreq) { ++(x->lo_bin); curfreq += x->c_fundamental ; } for (i = 0; i < x->L; i++) { x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L); } init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } t_int *pvharm_perform(t_int *w) { int i,j, in,on; int amp,freq,chan; int breaker = 0; float a,ainc,f,finc,address; float tmpfreq; t_pvharm *x = (t_pvharm *) (w[1]); t_float *inbuf = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *in3 = (t_float *)(w[4]); t_float *in4 = (t_float *)(w[5]); t_float *outbuf = (t_float *)(w[6]); t_int n = w[7]; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; int L = x->L; float fundamental = x->c_fundamental; float factor_in = x->c_factor_in; float factor_out = x->c_factor_out; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; float synt = x->synt; float P = x->P; float P2 = x->P2; float Iinv = x->Iinv; float myPInc = x->myPInc; float myPInc2 = x->myPInc2; float *table = x->table; float *lastamp = x->lastamp; float *lastamp2 = x->lastamp2; float *lastfreq = x->lastfreq; float *lastfreq2 = x->lastfreq2; float *bindex = x->index; float *bindex2 = x->index2; float *lastphase_in = x->c_lastphase_in; // float *lastphase_out = x->c_lastphase_out; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; int hi_bin = x->hi_bin; int lo_bin = x->lo_bin; in = on = x->inCount ; if( x->mute ){ for ( j = 0; j < n; j++ ){ *outbuf++ = 0.0; } return (w+8); } if( x->synt_connected ){ synt = *in4++; } if( x->pitch1_connected) { P = *in2++; myPInc = P * x->L/x->R; } if( x->pitch2_connected) { P2 = *in3++; myPInc2 = P2 * x->L/x->R; } in += D; on += I; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *inbuf++; } fold( input, Wanal, Nw, buffer, N, in ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, lastphase_in, fundamental, factor_in ); for ( chan = lo_bin; chan < hi_bin; chan++ ) { freq = ( amp = ( chan << 1 ) ) + 1; if ( channel[amp] < synt ){ breaker = 1; } if( breaker ) { breaker = 0 ; } else { tmpfreq = channel[freq] * myPInc; finc = ( tmpfreq - ( f = lastfreq[chan] ) )*Iinv; ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv; address = bindex[chan]; for ( n = 0; n < I; n++ ) { output[n] += a*table[ (int) address ]; address += f; while ( address >= L ) address -= L; while ( address < 0 ) address += L; a += ainc; f += finc; } lastfreq[chan] = tmpfreq; lastamp[chan] = channel[amp]; bindex[chan] = address; // OSC BANK 2 tmpfreq = channel[freq] * myPInc2; finc = ( tmpfreq - ( f = lastfreq2[chan] ) )*Iinv; ainc = ( channel[amp] - ( a = lastamp2[chan] ) )*Iinv; address = bindex2[chan]; for ( n = 0; n < I; n++ ) { output[n] += a*table[ (int) address ]; address += f; while ( address >= L ) address -= L; while ( address < 0 ) address += L; a += ainc; f += finc; } lastfreq2[chan] = tmpfreq; lastamp2[chan] = channel[amp]; bindex2[chan] = address; } } for ( j = 0; j < D; j++ ){ *outbuf++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } x->P = P; x->P2 = P2; x->inCount = in; return (w+8); } #if MSP void pvharm_float(t_pvharm *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->P = f; x->myPInc = x->P*x->L/x->R; } else if (inlet == 2) { x->P2 = f; x->myPInc2 = x->P2*x->L/x->R; } else if (inlet == 3) { x->synt = f; } } #endif void pvharm_mute(t_pvharm *x, t_floatarg state) { x->mute = (short)state; } void pvharm_dsp(t_pvharm *x, t_signal **sp, short *count) { #if MSP x->pitch1_connected = count[1]; x->pitch2_connected = count[2]; x->synt_connected = count[3]; #endif #if PD x->pitch1_connected = 1; x->pitch2_connected = 1; x->synt_connected = 1; #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; pvharm_init(x,1); } // post("pvharm: sampling rate is %f",sp[0]->s_sr ); dsp_add(pvharm_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/pvoc~-help.pd0000644000076500007650000000634612067450034015642 0ustar hanshans#N canvas -2 462 686 439 10; #N canvas 0 22 502 352 pvocblock 0; #X obj 27 158 outlet~; #X obj 27 42 inlet~; #X obj 80 13 inlet; #X obj 134 46 inlet; #X obj 213 69 inlet; #X text 145 87 args: lo-freq \, hi-freq \, overlap \, window-factor ; #X obj 27 85 pvoc~ 0 8000 4 4; #X obj 27 182 block~ 256; #X connect 1 0 6 0; #X connect 2 0 6 1; #X connect 3 0 6 2; #X connect 4 0 6 0; #X connect 6 0 0 0; #X restore 203 144 pd pvocblock; #X obj 203 203 dac~; #X floatatom 229 68 5 0.1 3 2 transpose transpose -; #X floatatom 255 99 5 0 0 2 thresh thresh -; #X msg 44 193 \; pd dsp \$1; #X obj 44 174 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 80 285 hsl 128 15 0.1 4 0 0 empty empty empty -2 -6 0 8 -261285 -1 -1 1931 1; #N canvas 242 216 504 402 messages 1; #X obj 70 293 outlet; #X floatatom 70 82 5 0 0 0 - - -; #X msg 70 112 highfreq \$1; #X floatatom 182 175 5 0 0 0 - - -; #X msg 182 204 lowfreq \$1; #X msg 70 53 8000; #X obj 70 27 loadbang; #X msg 182 154 0; #X obj 182 132 loadbang; #X obj 212 267 fftease-system; #X obj 161 48 hsl 128 15 500 8000 0 0 empty empty empty -2 -6 0 8 -68760 -1 -1 6900 1; #X obj 256 148 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -68760 -1 -1 0 1; #X text 149 22 maximum frequency to synthesize; #X text 252 124 minimum; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 1 0; #X connect 6 0 5 0; #X connect 7 0 3 0; #X connect 8 0 7 0; #X connect 9 0 0 0; #X connect 10 0 1 0; #X connect 11 0 3 0; #X restore 282 116 pd messages; #X obj 222 285 hsl 128 15 0 0.05 0 0 empty empty empty -2 -6 0 8 -227712 -1 -1 300 1; #X obj 219 311 s thresh; #X obj 77 311 s transpose; #X obj 77 233 loadbang; #X msg 77 264 1; #X obj 311 144 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -43049 -1 -1 5400 1; #X obj 203 170 *~ 0.01; #X text 444 143 gain; #N canvas 639 439 639 490 sndfile 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array pvoc-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ pvoc-sound1; #X msg 31 177 read -resize \$1 pvoc-sound1; #X connect 2 0 13 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 5 0; #X connect 12 1 7 0; #X connect 13 0 1 0; #X restore 203 31 pd sndfile; #X msg 219 249 0.001; #X text 286 27 <- load a soundfile here; #X text 75 345 pvoc~ allows you to change the pitch of the input sound without changing its speed. Optional arguments: low frequency to synthesize \, high frequency to synthesize. These parameters \, together with the pvoc~ block size will determine CPU load.; #X connect 0 0 14 0; #X connect 2 0 0 1; #X connect 3 0 0 2; #X connect 5 0 4 0; #X connect 6 0 10 0; #X connect 7 0 0 3; #X connect 8 0 9 0; #X connect 11 0 12 0; #X connect 11 0 17 0; #X connect 12 0 6 0; #X connect 13 0 14 1; #X connect 14 0 1 0; #X connect 14 0 1 1; #X connect 16 0 0 0; #X connect 17 0 8 0; fftease-2.5.2.git20121005/pvoc~.c0000644000076500007650000003250512067450034014527 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvoc_class; #endif #if PD static t_class *pvoc_class; #endif #define OBJECT_NAME "pvoc~" typedef struct _pvoc { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // for oscbank int NP; float P; int L; int first; float Iinv; float *lastamp; float *lastfreq; float *index; float *table; float myPInc; float ffac; // float lofreq; float hifreq; int lo_bin; int hi_bin; float topfreq; float synt; // for fast fft float mult; float *trigland; int *bitshuffle; // int bypass_state; int pitch_connected; int synt_connected; int overlap; int winfac; short mute; } t_pvoc; void *pvoc_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *pvoc_perform(t_int *w); void pvoc_dsp(t_pvoc *x, t_signal **sp, short *count); void pvoc_assist(t_pvoc *x, void *b, long m, long a, char *s); void pvoc_bypass(t_pvoc *x, t_floatarg state);//Pd does not accept A_LONG void pvoc_float(t_pvoc *x, double f); void pvoc_free(t_pvoc *x); void pvoc_mute(t_pvoc *x, t_floatarg tog); void pvoc_init(t_pvoc *x, short initialized); void pvoc_lowfreq(t_pvoc *x, t_floatarg f); void pvoc_highfreq(t_pvoc *x, t_floatarg f); void pvoc_overlap(t_pvoc *x, t_floatarg o); void pvoc_winfac(t_pvoc *x, t_floatarg f); void pvoc_fftinfo(t_pvoc *x);; #if PD /* Pd Initialization */ void pvoc_tilde_setup(void) { pvoc_class = class_new(gensym("pvoc~"), (t_newmethod)pvoc_new, (t_method)pvoc_free ,sizeof(t_pvoc), 0,A_GIMME,0); CLASS_MAINSIGNALIN(pvoc_class, t_pvoc, x_f); class_addmethod(pvoc_class, (t_method)pvoc_dsp, gensym("dsp"), 0); class_addmethod(pvoc_class, (t_method)pvoc_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_highfreq, gensym("highfreq"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_lowfreq, gensym("lowfreq"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(pvoc_class, (t_method)pvoc_fftinfo, gensym("fftinfo"),0); class_addmethod(pvoc_class, (t_method)pvoc_assist, gensym("assist"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if MSP void main(void) { setup((t_messlist **)&pvoc_class, (method)pvoc_new, (method)pvoc_free, (short)sizeof(t_pvoc), 0L, A_GIMME, 0); addmess((method)pvoc_dsp, "dsp", A_CANT, 0); addmess((method)pvoc_assist,"assist",A_CANT,0); addmess((method)pvoc_bypass,"bypass",A_DEFFLOAT,0); addmess((method)pvoc_mute,"mute",A_DEFFLOAT,0); addmess((method)pvoc_lowfreq,"lowfreq",A_DEFFLOAT,0); addmess((method)pvoc_highfreq,"highfreq",A_DEFFLOAT,0); addmess((method)pvoc_fftinfo,"fftinfo",0); addmess((method)pvoc_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)pvoc_winfac, "winfac", A_DEFFLOAT, 0); addfloat((method)pvoc_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void pvoc_mute(t_pvoc *x, t_floatarg tog) { x->mute = (short)tog; } void pvoc_overlap(t_pvoc *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; pvoc_init(x,1); } void pvoc_winfac(t_pvoc *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; pvoc_init(x,2); } void pvoc_fftinfo(t_pvoc *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void pvoc_free(t_pvoc *x ){ #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->lastamp,0); freebytes(x->lastfreq,0); freebytes(x->index,0); freebytes(x->table,0); } /*MSP only but Pd crashes without it maybe because of function definition??? */ void pvoc_assist (t_pvoc *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Pitch Modification Factor"); break; case 2: sprintf(dst,"(signal/float) Synthesis Threshold"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void pvoc_highfreq(t_pvoc *x, t_floatarg f) { float curfreq; if(f < x->lofreq){ error("current minimum is %f",x->lofreq); return; } if(f > x->R/2 ){ f = x->R/2; } x->hifreq = f; x->hi_bin = 1; curfreq = 0; while(curfreq < x->hifreq) { ++(x->hi_bin); curfreq += x->c_fundamental; } } void pvoc_lowfreq(t_pvoc *x, t_floatarg f) { float curfreq; if(f > x->hifreq){ error("current maximum is %f",x->lofreq); return; } if(f < 0 ){ f = 0; } x->lofreq = f; x->lo_bin = 0; curfreq = 0; while( curfreq < x->lofreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } } void pvoc_init(t_pvoc *x, short initialized) { int i; float curfreq; if(!x->R)//temp init if MSP functions returned zero x->R = 44100; if(!x->D) x->D = 256; if(x->P <= 0) x->P = 1.0; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 2; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = x->N / 2; x->Nw2 = x->Nw / 2; x->inCount = -(x->Nw); x->bypass_state = 0; x->mult = 1. / (float) x->N; x->pitch_connected = 0; x->synt_connected = 0; x->mute = 0; x->synt = .000001; x->L = 8192 ; x->c_fundamental = (float) x->R/(float)( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->Iinv = 1./x->D; x->myPInc = x->P*x->L/x->R; x->ffac = x->P * PI/x->N; if(!initialized){ x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->lastamp = (float *) getbytes( (MAX_N+1) * sizeof(float) ); x->lastfreq = (float *) getbytes( (MAX_N+1) * sizeof(float) ); x->index = (float *) getbytes( (MAX_N+1) * sizeof(float) ); x->table = (float *) getbytes( x->L * sizeof(float) ); x->P = 1.0; x->ffac = x->P * PI/MAX_N; } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); memset((char *)x->lastamp,0,(x->N+1) * sizeof(float)); memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float)); memset((char *)x->index,0,(x->N+1) * sizeof(float)); for ( i = 0; i < x->L; i++ ) { x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L); } init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); if( x->hifreq < x->c_fundamental ) { x->hifreq = 3000.0 ; } x->hi_bin = 1; curfreq = 0; while( curfreq < x->hifreq ) { ++(x->hi_bin); curfreq += x->c_fundamental ; } x->lo_bin = 0; curfreq = 0; while( curfreq < x->lofreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } } void *pvoc_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_pvoc *x = (t_pvoc *)newobject(pvoc_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_pvoc *x = (t_pvoc *)pd_new(pvoc_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->lofreq = atom_getfloatarg(0,argc,argv); x->hifreq = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(x->lofreq <0 || x->lofreq> 22050) x->lofreq = 0; if(x->hifreq <50 || x->hifreq> 22050) x->hifreq = 4000; if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 2; } x->R = sys_getsr(); x->D = sys_getblksize(); pvoc_init(x,0); return (x); } t_int *pvoc_perform(t_int *w) { int i,j, in,on; int amp,freq,chan,L = 8192; float a,ainc,f,finc,address; int breaker = 0; t_pvoc *x = (t_pvoc *) (w[1]); t_float *inbuf = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *in3 = (t_float *)(w[4]); t_float *outbuf = (t_float *)(w[5]); t_int n = w[6]; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float fundamental = x->c_fundamental; float factor_in = x->c_factor_in; float factor_out = x->c_factor_out; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; float synt = x->synt; float P = x->P; float Iinv = 1./x->D; float myPInc = x->myPInc; float *table = x->table; float *lastamp = x->lastamp ; float *lastfreq = x->lastfreq ; float *bindex = x->index; float *lastphase_in = x->c_lastphase_in; float *lastphase_out = x->c_lastphase_out; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; int hi_bin = x->hi_bin; int lo_bin = x->lo_bin; in = on = x->inCount ; if(x->mute){ while(n--){ *outbuf++ = 0; } return w+7; } #if MSP if(x->pitch_connected) { P = *in2; myPInc = P * (float) x->L / (float)x->R; } if (x->synt_connected) { synt = *in3; } #endif // Pd has superior float/signal inlet treatment #if PD P = *in2; synt = *in3; myPInc = P * (float) x->L / (float)x->R; #endif if (x->bypass_state) { for( j = 0; j < D; j++ ) { *outbuf++ = *inbuf++; } return w+7; } in = on = x->inCount ; in += D; on += I; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) {// unneeded loop variable input[j] = *inbuf++; } fold( input, Wanal, Nw, buffer, N, in ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, lastphase_in, fundamental, factor_in ); // start osc bank for ( chan = lo_bin; chan < hi_bin; chan++ ) { freq = ( amp = ( chan << 1 ) ) + 1; if ( channel[amp] < synt ){ breaker = 1; } if( breaker ) { breaker = 0 ; } else { channel[freq] *= myPInc; finc = ( channel[freq] - ( f = lastfreq[chan] ) )*Iinv; ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv; address = bindex[chan]; for ( n = 0; n < I; n++ ) { output[n] += a*table[ (int) address ]; address += f; while ( address >= L ) address -= L; while ( address < 0 ) address += L; a += ainc; f += finc; } lastfreq[chan] = channel[freq]; lastamp[chan] = channel[amp]; bindex[chan] = address; } } for ( j = 0; j < D; j++ ){ *outbuf++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } // restore state variables x->inCount = in; return (w+7); } void pvoc_bypass(t_pvoc *x, t_floatarg state) { x->bypass_state = state; } #if MSP void pvoc_float(t_pvoc *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->P = (float)f; x->myPInc = x->P*x->L/x->R; } else if (inlet == 2) { x->synt = (float)f; } } #endif void pvoc_dsp(t_pvoc *x, t_signal **sp, short *count) { #if MSP // these blew up Pd x->pitch_connected = count[1]; x->synt_connected = count[2]; #endif if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr ){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; pvoc_init(x,1); } dsp_add(pvoc_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/pvtuner.h0000644000076500007650000000457412067450034015077 0ustar hanshans#define MAXTONES (1024) #define BASE_FREQ (27.5) /* low A */ #define DIATONIC 0 #define EASTERN 1 #define MINOR 2 #define EQ12 3 #define PENTATONIC 4 #define MAJOR_ADDED_SIXTH 5 #define MINOR_ADDED_SIXTH 6 #define MAJOR_SEVENTH_CHORD 7 #define MINOR_SEVENTH_CHORD 8 #define DOMINANT_SEVENTH_CHORD 9 #define EQ8 10 #define PENTACLUST 11 #define QUARTERCLUST 12 #define EQ5 13 #define SLENDRO 14 #define PELOG 15 #define IMPORTED_SCALE 16 #define DEFAULT_VECTOR_SIZE 512 static t_class *pvtuner_class; typedef struct _pvtuner { t_object x_obj; t_float x_f; int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // for oscbank int NP; float P; int L; int first; float Iinv; float *lastamp; float *lastfreq; float *bindex; float *table; float myPInc; float ffac; // int lo_bin; int hi_bin; float topfreq; float synt; float myPI; float TWOmyPI; // for fast fft float mult; float *trigland; int *bitshuffle; // float *prebuffer; float *postbuffer; // int bypass_state; int pitch_connected; int synt_connected; // TUNING float *pitchgrid ; float pbase ; int scale_steps; short current_scale; short mute; // float TWOPIoL; float user_lofreq; float user_hifreq; int vector_size; float funda; float curfreq; int overlap; int window_factor; float tabscale; int quality; int scale_len; } t_pvtuner; float closestf(float test, float *arr) ; void pvtuner_diatonic( t_pvtuner *x ); void pvtuner_eastern( t_pvtuner *x ); void pvtuner_minor( t_pvtuner *x ); void pvtuner_eq12( t_pvtuner *x ); void pvtuner_pentatonic( t_pvtuner *x ); void pvtuner_major_added_sixth( t_pvtuner *x ); void pvtuner_minor_added_sixth( t_pvtuner *x ); void pvtuner_major_seventh_chord( t_pvtuner *x ); void pvtuner_minor_seventh_chord( t_pvtuner *x ); void pvtuner_dominant_seventh_chord( t_pvtuner *x ); void pvtuner_eq8( t_pvtuner *x ); void pvtuner_pentaclust( t_pvtuner *x ); void pvtuner_quarterclust( t_pvtuner *x ); void pvtuner_eq5( t_pvtuner *x ); void pvtuner_slendro( t_pvtuner *x ); void pvtuner_pelog( t_pvtuner *x ); void pvtuner_update_imported( t_pvtuner *x ); fftease-2.5.2.git20121005/pvtuner~-help.pd0000644000076500007650000001060712067452034016373 0ustar hanshans#N canvas 189 203 449 413 10; #N canvas 0 22 502 352 tuneblock 0; #X obj 33 21 inlet~; #X obj 97 20 inlet; #X obj 161 25 inlet; #X obj 242 56 inlet; #X obj 33 203 outlet~; #X obj 33 102 pvtuner~ 0 5000; #X obj 147 208 block~ 256; #X connect 0 0 5 0; #X connect 1 0 5 1; #X connect 2 0 5 2; #X connect 3 0 5 0; #X connect 5 0 4 0; #X restore 24 141 pd tuneblock; #X obj 24 3 noise~; #X floatatom 50 71 5 0.1 2 1 transpose - -; #X obj 24 242 dac~; #X msg 81 239 \; pd dsp \$1; #X obj 81 216 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #N canvas 154 403 400 321 messages 0; #X obj 21 216 outlet; #N canvas 0 22 536 459 built-in-scales 0; #X msg 11 30 major_seventh_chord; #X msg 41 49 minor_seventh_chord; #X msg 113 88 minor_added_sixth; #X msg 84 68 major_added_sixth; #X msg 320 8 pelog; #X msg 324 36 slendro; #X obj 46 312 outlet; #X msg 296 97 eq5; #X msg 302 117 eq8; #X msg 309 138 eq12; #X msg -1 11 dominant_seventh_chord; #X msg 276 181 minor; #X msg 284 208 pentatonic; #X msg 282 233 eastern; #X msg 255 261 pentaclust; #X msg 270 282 quarterclust; #X connect 0 0 6 0; #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 5 0 6 0; #X connect 7 0 6 0; #X connect 8 0 6 0; #X connect 9 0 6 0; #X connect 10 0 6 0; #X connect 11 0 6 0; #X connect 12 0 6 0; #X connect 13 0 6 0; #X connect 14 0 6 0; #X connect 15 0 6 0; #X restore 21 27 pd built-in-scales; #N canvas 520 357 631 434 more-scales 0; #X msg 77 94 27.5 41.25 55 82.5 110 165 220 330 440 660 880 1320 1760 2640 3520 5280 7040 10560 14080 21120; #X text 80 78 define scale as ordered list of numbers; #X obj 77 371 outlet; #X msg 165 148 import_scale examples/blue3.scale; #X text 161 130 you can even load a file \, but be sure to use a full pathname; #X msg 165 170 import_scale examples/13et.scale; #X msg 165 190 import_scale examples/24et.scale; #X msg 165 210 import_scale examples/4th.scale; #X msg 165 230 import_scale examples/blue3.scale; #X msg 165 250 import_scale examples/m3chord.scale; #X msg 165 270 import_scale examples/m3M3.scale; #X msg 165 290 import_scale examples/octfifth.scale; #X msg 165 310 import_scale examples/test.scale; #X text 217 337 There are also included perl scripts for generating the scale files: examples/scale*.pl; #X connect 0 0 2 0; #X connect 3 0 2 0; #X connect 5 0 2 0; #X connect 6 0 2 0; #X connect 7 0 2 0; #X connect 8 0 2 0; #X connect 9 0 2 0; #X connect 10 0 2 0; #X connect 11 0 2 0; #X connect 12 0 2 0; #X restore 48 48 pd more-scales; #X obj 130 154 fftease-system; #N canvas 968 224 694 704 frequency-management 0; #X obj 37 509 outlet; #X msg 37 122 toptune \$1; #X msg 187 129 topfreq \$1; #X floatatom 37 93 5 0 0 0 - - -; #X floatatom 187 98 5 0 0 0 - - -; #X obj 160 31 hsl 200 15 500 9000 0 0 empty empty empty -2 -6 0 8 -126035 -1 -1 0 1; #X obj 157 57 t f f; #X msg 258 181 frequency_range 500 2000; #X msg 258 207 frequency_range 0 6000; #X text 45 106 highest tuned freq; #X text 191 114 highest synthesized freq; #X text 256 166 set synthesize range; #X msg 155 471 basefreq \$1; #X floatatom 155 454 5 0 0 0 - - -; #X obj 158 433 hsl 128 15 27.5 500 0 0 empty empty empty -2 -6 0 8 -261681 -1 -1 0 1; #X msg 155 406 27.5; #X obj 155 381 loadbang; #X text 190 409 set base frequency for scale; #X obj 40 12 hsl 200 15 500 9000 0 0 empty empty empty -2 -6 0 8 -126035 -1 -1 0 1; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 1 0; #X connect 4 0 2 0; #X connect 5 0 6 0; #X connect 6 0 3 0; #X connect 6 1 4 0; #X connect 7 0 0 0; #X connect 8 0 0 0; #X connect 12 0 0 0; #X connect 13 0 12 0; #X connect 14 0 13 0; #X connect 15 0 14 0; #X connect 16 0 15 0; #X connect 18 0 3 0; #X restore 56 73 pd frequency-management; #X msg 109 116 binfo; #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 5 0 0 0; #X restore 103 115 pd messages; #X obj 167 26 loadbang; #X msg 50 42 1; #X obj 71 163 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -123336 -1 -1 0 1; #X floatatom 68 181 5 0 0 0 - - -; #X floatatom 76 91 5 0 0 1 synth-threshold - -; #X msg 167 47 0.001; #X text 188 116 <- check it; #X obj 24 199 *~ 0.01; #X text 27 295 pvtuner~ tunes sounds to scales.; #X connect 0 0 14 0; #X connect 1 0 0 0; #X connect 2 0 0 1; #X connect 5 0 4 0; #X connect 6 0 0 3; #X connect 7 0 8 0; #X connect 7 0 12 0; #X connect 8 0 2 0; #X connect 9 0 10 0; #X connect 10 0 14 1; #X connect 11 0 0 2; #X connect 12 0 11 0; #X connect 14 0 3 0; #X connect 14 0 3 1; fftease-2.5.2.git20121005/pvtuner~.c0000644000076500007650000007771012067450034015272 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvtuner_class; #endif #if PD static t_class *pvtuner_class; #endif #define OBJECT_NAME "pvtuner~" #define MAXTONES (1024) #define BASE_FREQ (27.5) /* low A */ #define DIATONIC 0 #define EASTERN 1 #define MINOR 2 #define EQ12 3 #define PENTATONIC 4 #define MAJOR_ADDED_SIXTH 5 #define MINOR_ADDED_SIXTH 6 #define ADDED_SIXTH_MAJOR 5 #define ADDED_SIXTH_MINOR 6 #define MAJOR_SEVENTH_CHORD 7 #define MINOR_SEVENTH_CHORD 8 #define DOMINANT_SEVENTH_CHORD 9 #define EQ8 10 #define PENTACLUST 11 #define QUARTERCLUST 12 #define EQ5 13 #define SLENDRO 14 #define PELOG 15 #define IMPORTED_SCALE 16 typedef struct _pvtuner { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float *bindex; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // for oscbank int NP; float P; int L; int first; float Iinv; float *lastamp; float *lastfreq; // float *osc_index; float *table; float myPInc; float ffac; // int lo_bin; int hi_bin; int hi_tune_bin; float topfreq; float synt; // for fast fft float mult; float *trigland; int *bitshuffle; // // float *prebuffer; // float *postbuffer; // int bypass_state; int pitch_connected; int synt_connected; // TUNING float *pitchgrid ; float pbase ; int scale_steps; short current_scale; short mute; // float lofreq; float hifreq; int vs; float funda; float curfreq; int overlap; int winfac; float tabscale; // int quality; int scale_len; } t_pvtuner; float closestf(float test, float *arr) ; void pvtuner_diatonic( t_pvtuner *x ); void pvtuner_eastern( t_pvtuner *x ); void pvtuner_minor( t_pvtuner *x ); void pvtuner_eq12( t_pvtuner *x ); void pvtuner_pentatonic( t_pvtuner *x ); void pvtuner_major_added_sixth( t_pvtuner *x ); void pvtuner_minor_added_sixth( t_pvtuner *x ); void pvtuner_major_seventh_chord( t_pvtuner *x ); void pvtuner_minor_seventh_chord( t_pvtuner *x ); void pvtuner_dominant_seventh_chord( t_pvtuner *x ); void pvtuner_eq8( t_pvtuner *x ); void pvtuner_pentaclust( t_pvtuner *x ); void pvtuner_quarterclust( t_pvtuner *x ); void pvtuner_eq5( t_pvtuner *x ); void pvtuner_slendro( t_pvtuner *x ); void pvtuner_pelog( t_pvtuner *x ); void pvtuner_update_imported( t_pvtuner *x ); void pvtuner_init(t_pvtuner *x,short initialized); void *pvtuner_new(t_symbol *s, int argc, t_atom *argv); void pvtuner_import_scale(t_pvtuner *x, t_symbol *filename); void pvtuner_list (t_pvtuner *x, t_symbol *msg, short argc, t_atom *argv); void pvtuner_topfreq( t_pvtuner *x, t_floatarg f ); void pvtuner_toptune( t_pvtuner *x, t_floatarg f ); void pvtuner_frequency_range(t_pvtuner *x, t_floatarg lo, t_floatarg hi); t_int *pvtuner_perform(t_int *w); void pvtuner_basefreq( t_pvtuner *x, t_floatarg bassfreq); void pvtuner_free(t_pvtuner *x); void pvtuner_assist (t_pvtuner *x, void *b, long msg, long arg, char *dst); void pvtuner_bypass(t_pvtuner *x, t_floatarg state); void pvtuner_mute(t_pvtuner *x, t_floatarg state); void pvtuner_dsp(t_pvtuner *x, t_signal **sp, short *count); void pvtuner_float(t_pvtuner *x, double f) ; void pvtuner_toptune(t_pvtuner *x, t_floatarg f); void pvtuner_topfreq(t_pvtuner *x, t_floatarg f); void pvtuner_list (t_pvtuner *x, t_symbol *msg, short argc, t_atom *argv); void pvtuner_fftinfo(t_pvtuner *x); void pvtuner_overlap(t_pvtuner *x, t_floatarg f); void pvtuner_winfac(t_pvtuner *x, t_floatarg f); void pvtuner_binfo(t_pvtuner *x); void *pvtuner_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_pvtuner *x = (t_pvtuner *)newobject(pvtuner_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_pvtuner *x = (t_pvtuner *)pd_new(pvtuner_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->R = sys_getsr(); x->D = sys_getblksize(); x->lofreq = atom_getfloatarg(0, argc, argv); x->hifreq = atom_getfloatarg(1, argc, argv); x->overlap = atom_getfloatarg(2, argc, argv); x->winfac = atom_getfloatarg(3, argc, argv); if(x->lofreq <= 0 || x->lofreq >= x->R/2) x->lofreq = 0; if(x->hifreq <= 0 || x->hifreq > x->R/2) x->hifreq = 4000.0; pvtuner_init(x,0); return (x); } void pvtuner_init(t_pvtuner *x,short initialized) { int i, j; int mem; float curfreq; if(!x->R)//temp init if MSP functions returned zero x->R = 44100; if(!x->D) x->D = 256; if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 2; x->Iinv = 1./x->D; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/(float)( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->P = 1.0 ; // default x->bypass_state = 0; x->mute = 0; x->L = 8192; x->synt = .000001; mem = (MAX_Nw)*sizeof(float); x->Wanal = (float *) getbytes(mem); x->Wsyn = (float *) getbytes(mem); x->Hwin = (float *) getbytes(mem); x->input = (float *) getbytes(mem); x->output = (float *) getbytes(mem); mem = (MAX_N)*sizeof(float); x->buffer = (float *) getbytes(mem); mem = (MAX_N+2)*sizeof(float); x->channel = (float *) getbytes(mem); mem = (MAX_N*2)*sizeof(int); x->bitshuffle = (int *) getbytes(mem); mem = (MAX_N*2)*sizeof(float); x->trigland = (float *) getbytes(mem); mem = (MAXTONES+1)*sizeof(float); x->pitchgrid = (float *) getbytes(mem); mem = (MAX_N+1)*sizeof(float); x->lastamp = (float *) getbytes(mem); x->lastfreq = (float *) getbytes(mem); x->bindex = (float *) getbytes(mem); mem = (x->L)*sizeof(float); x->table = (float *) getbytes(mem); mem = (MAX_N2+1)*sizeof(float); x->c_lastphase_in = (float *) getbytes(mem); x->c_lastphase_out = (float *)getbytes(mem); x->pbase = BASE_FREQ; pvtuner_diatonic(x);// default scale } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->lastamp,0,(x->N+1) * sizeof(float)); memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float)); memset((char *)x->bindex,0,(x->N+1) * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); for ( i = 0; i < x->L; i++ ) { x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L); } if( x->hifreq < x->c_fundamental ) { x->hifreq = 3000.0 ; } x->hi_bin = 1; x->curfreq = 0; while( x->curfreq < x->hifreq ) { ++(x->hi_bin); x->curfreq += x->c_fundamental ; } x->lo_bin = 0; x->curfreq = 0; while( x->curfreq < x->lofreq ) { ++(x->lo_bin); x->curfreq += x->c_fundamental ; } if( x->hi_bin >= x->N2 ) x->hi_bin = x->N2 - 1; x->hi_tune_bin = x->hi_bin; x->myPInc = x->P*x->L/x->R; x->ffac = x->P * PI/x->N; init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } void pvtuner_toptune(t_pvtuner *x, t_floatarg f) { int tbin; float curfreq; float fundamental = x->c_fundamental; tbin = 1; curfreq = 0; if( f < 0 || f > x->R / 2.0 ){ error("frequency %f out of range", f); return; } while( curfreq < f ) { ++tbin; curfreq += fundamental ; } if( tbin > x->lo_bin && tbin <= x->hi_bin ){ x->hi_tune_bin = tbin; } else { error("bin %d out of range", tbin); } } void pvtuner_topfreq(t_pvtuner *x, t_floatarg f) { int tbin; float curfreq; float fundamental = x->c_fundamental; tbin = 1; curfreq = 0; if( f < 0 || f > x->R / 2.0 ){ error("frequency %f out of range", f); return; } while( curfreq < f ) { ++tbin; curfreq += fundamental ; } if( tbin > x->lo_bin && tbin < x->N2 - 1 ){ x->hi_bin = tbin; } else { error("bin %d out of range", tbin); } } void pvtuner_list (t_pvtuner *x, t_symbol *msg, short argc, t_atom *argv) { float val; float *pitchgrid = x->pitchgrid; int i = 0; if( ! atom_getfloatarg(i,argc,argv) ){ error("either zero length scale or 0.0 (prohibited) is first value"); return; } /* first set every value to maximum */ for(i=0; i < MAXTONES; i++){ pitchgrid[i] = (float)x->R / 2.0; } for( i = 0; i < argc; i++ ){ pitchgrid[ i ] = atom_getfloatarg(i,argc,argv) ; } x->scale_len = i; // post("list scale is length %d", i); x->current_scale = IMPORTED_SCALE; } void pvtuner_import_scale(t_pvtuner *x, t_symbol *filename) // seems to be broken now { FILE *fp; float val; float *pitchgrid = x->pitchgrid; int scale_len = x->scale_len; if( ! (fp = fopen( filename->s_name, "r")) ){ error("could not open file %s", filename); return; } scale_len = 0; while( ( (fscanf(fp, "%f", &val)) != EOF) && (scale_len < MAXTONES) ){ pitchgrid[ scale_len++ ] = val; } fclose( fp ); x->scale_len = scale_len; x->current_scale = IMPORTED_SCALE; // post("read %s", filename->s_name); } void pvtuner_binfo(t_pvtuner *x) { post("%s: frequency targets: %f %f", OBJECT_NAME, x->lofreq, x->hifreq); post("synthesizing %d bins, from %d to %d",(x->hi_bin - x->lo_bin), x->lo_bin, x->hi_bin); } void pvtuner_frequency_range(t_pvtuner *x, t_floatarg lo, t_floatarg hi) { x->lofreq = lo ; x->hifreq = hi; if( lo >= hi ){ error("low frequency must be lower than high frequency"); return; } x->curfreq = 0; x->hi_bin = 0; while( x->curfreq < x->hifreq ) { ++(x->hi_bin); x->curfreq += x->c_fundamental ; } x->curfreq = 0; x->lo_bin = 0; while( x->curfreq < x->lofreq ) { ++(x->lo_bin); x->curfreq += x->c_fundamental ; } } t_int *pvtuner_perform(t_int *w) { int i,j, in,on; int amp,freq,chan; float a,ainc,f,finc,address; int breaker = 0; t_pvtuner *x = (t_pvtuner *) (w[1]); t_float *inbuf = (t_float *)(w[2]); t_float *in2 = (t_float *)(w[3]); t_float *in3 = (t_float *)(w[4]); t_float *outbuf = (t_float *)(w[5]); int n = (int)(w[6]); int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float fundamental = x->c_fundamental; float factor_in = x->c_factor_in; float factor_out = x->c_factor_out; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; float synt = x->synt; float P = x->P; // myPItchfac float Iinv = x->Iinv; float myPInc = x->myPInc; int L = x->L; /* assign pointers */ float *table = x->table; float *lastamp = x->lastamp ; float *lastfreq = x->lastfreq ; float *bindex = x->bindex; float *lastphase_in = x->c_lastphase_in; float *lastphase_out = x->c_lastphase_out; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; float *pitchgrid = x->pitchgrid; int hi_bin = x->hi_bin; int lo_bin = x->lo_bin; int hi_tune_bin = x->hi_tune_bin; int inCount = x->inCount; in = on = x->inCount ; if( x->pitch_connected ) { x->P = *in2++ ; // myPItchfac x->myPInc = x->P*(float)x->L/(float)x->R; } if ( x->synt_connected ) { synt = *in3++ ; } if (x->bypass_state) { // just send through for( j = 0; j < D; j++ ) { *outbuf++ = *inbuf++; } return (w+7); } if (x->mute) { for( j = 0; j < D; j++ ) { *outbuf++ = 0.0; } return (w+7); } inCount += D; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *inbuf++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, lastphase_in, fundamental, factor_in ); // start osc bank for ( chan = lo_bin; chan < hi_bin; chan++ ) { freq = ( amp = ( chan << 1 ) ) + 1; if ( channel[amp] < synt ){ breaker = 1; } if( breaker ) { breaker = 0 ; } else { if(chan <= hi_tune_bin){ channel[freq] = closestf(channel[freq], pitchgrid); } channel[freq] *= myPInc; finc = ( channel[freq] - ( f = lastfreq[chan] ) )*Iinv; ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv; address = bindex[chan]; for ( n = 0; n < I; n++ ) { output[n] += a*table[ (int) address ]; address += f; while ( address >= L ) address -= L; while ( address < 0 ) address += L; a += ainc; f += finc; } lastfreq[chan] = channel[freq]; lastamp[chan] = channel[amp]; bindex[chan] = address; } } for ( j = 0; j < D; j++ ){ *outbuf++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } x->inCount = inCount % Nw; return (w+7); } void pvtuner_basefreq( t_pvtuner *x, t_floatarg bassfreq) { if( bassfreq < 10. ) bassfreq = 10. ; if( bassfreq > 10000. ) bassfreq = 10000.; x->pbase = bassfreq; if( x->current_scale == IMPORTED_SCALE ){ pvtuner_update_imported( x ); } else if( x->current_scale == DIATONIC ){ pvtuner_diatonic( x ); } else if( x->current_scale == EASTERN) { pvtuner_eastern( x ); } else if( x->current_scale == MINOR) { pvtuner_minor( x ); } else if( x->current_scale == EQ12) { pvtuner_eq12( x ); } else if( x->current_scale == PENTATONIC) { pvtuner_pentatonic( x ); } else if( x->current_scale == MAJOR_ADDED_SIXTH) { pvtuner_major_added_sixth( x ); } else if( x->current_scale == MINOR_ADDED_SIXTH) { pvtuner_minor_added_sixth( x ); } else if( x->current_scale == MAJOR_SEVENTH_CHORD) { pvtuner_major_seventh_chord( x ); } else if( x->current_scale == MINOR_SEVENTH_CHORD) { pvtuner_minor_seventh_chord( x ); } else if( x->current_scale == DOMINANT_SEVENTH_CHORD) { pvtuner_dominant_seventh_chord( x ); } else if( x->current_scale == EQ8) { pvtuner_eq8( x ); } else if( x->current_scale == PENTACLUST) { pvtuner_pentaclust( x ); } else if( x->current_scale == QUARTERCLUST ) { pvtuner_quarterclust( x ); } else if( x->current_scale == EQ5 ) { pvtuner_eq5( x ); } else if( x->current_scale == SLENDRO ) { pvtuner_slendro( x ); } else if( x->current_scale == PELOG ) { pvtuner_pelog( x ); } else { post("unknown scale"); } } void pvtuner_free(t_pvtuner *x) { #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->lastamp,0); freebytes(x->lastfreq,0); freebytes(x->bindex,0); freebytes(x->table,0); freebytes(x->pitchgrid,0); } #if MSP void pvtuner_assist (t_pvtuner *x, void *b, long msg, long arg, char *dst) { if (msg==ASSIST_INLET) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Pitch Modification Factor"); break; case 2: sprintf(dst,"(signal/float) Synthesis Threshold"); break; } } else if (msg==ASSIST_OUTLET) { sprintf(dst,"(signal) Output"); } } #endif #if PD void pvtuner_assist (t_pvtuner *x, void *b, long msg, long arg, char *dst) { post("INLETS: input pitch_factor synthesis_threshold"); post("ARGUMENTS: lo_freq hi_freq"); } #endif void pvtuner_update_imported( t_pvtuner *x ){ float *pitchgrid = x->pitchgrid; float factor = x->pbase / pitchgrid[0]; int i; for( i = 0; i < x->scale_len; i++ ) pitchgrid[i] *= factor; } void pvtuner_diatonic( t_pvtuner *x ){ int i, j; // post("calling diatonic for vs %d",x->vs); x->pitchgrid[0] = x->pbase; x->pitchgrid[1] = x->pbase * (9./8.); x->pitchgrid[2] = x->pbase * (5./4.); x->pitchgrid[3] = x->pbase * (4./3.); x->pitchgrid[4] = x->pbase * (3./2.); x->pitchgrid[5] = x->pbase * (27./16.); x->pitchgrid[6] = x->pbase * (15./8.); x->scale_steps = 7; for( i = 1; i < 10; i++ ){ for( j = 0; j < x->scale_steps; j++ ){ x->pitchgrid[ i*x->scale_steps + j] = x->pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = DIATONIC ; } void pvtuner_minor( t_pvtuner *x ){ int i, j; x->pitchgrid[0] = x->pbase; x->pitchgrid[1] = x->pbase * (9./8.); x->pitchgrid[2] = x->pbase * (6./5.); x->pitchgrid[3] = x->pbase * (4./3.); x->pitchgrid[4] = x->pbase * (3./2.); x->pitchgrid[5] = x->pbase * (8./5.); x->pitchgrid[6] = x->pbase * (9./5.); x->scale_steps = 7; for( i = 1; i < 10; i++ ){ for( j = 0; j < x->scale_steps; j++ ){ x->pitchgrid[ i*x->scale_steps + j] = x->pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = MINOR ; } void pvtuner_pentatonic( t_pvtuner *x ){ int i, j; x->pitchgrid[0] = x->pbase; x->pitchgrid[1] = x->pbase * (9./8.); x->pitchgrid[2] = x->pbase * (81./64.); x->pitchgrid[3] = x->pbase * (3./2.); x->pitchgrid[4] = x->pbase * (27./16.); x->scale_steps = 5; for( i = 1; i < 10; i++ ){ for( j = 0; j < x->scale_steps; j++ ){ x->pitchgrid[ i*x->scale_steps + j] = x->pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = PENTATONIC ; } void pvtuner_eq12( t_pvtuner *x ){ int i, j; float expon; x->pitchgrid[0] = x->pbase; for( i = 0; i < 12; i++ ){ expon = (float) i / 12.0 ; x->pitchgrid[i] = x->pbase * pow(2.0,expon); } x->scale_steps = 12; for( i = 1; i < 10; i++ ){ for( j = 0; j < x->scale_steps; j++ ){ x->pitchgrid[ i*x->scale_steps + j] = x->pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = EQ12 ; } void pvtuner_major_added_sixth( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.259921; pitchgrid[2] = pbase * 1.498307; pitchgrid[3] = pbase * 1.681793; scale_steps = 4 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = MAJOR_ADDED_SIXTH; x->scale_steps = scale_steps; } void pvtuner_minor_added_sixth( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.189207; pitchgrid[2] = pbase * 1.498307; pitchgrid[3] = pbase * 1.587401; scale_steps = 4 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = MINOR_ADDED_SIXTH; x->scale_steps = scale_steps; } void pvtuner_major_seventh_chord( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.25; pitchgrid[2] = pbase * 1.5; pitchgrid[3] = pbase * 1.875; scale_steps = 4 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = MAJOR_SEVENTH_CHORD; x->scale_steps = scale_steps; } void pvtuner_minor_seventh_chord( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.2; pitchgrid[2] = pbase * 1.5; pitchgrid[3] = pbase * 1.781797; scale_steps = 4 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = MINOR_SEVENTH_CHORD; x->scale_steps = scale_steps; } void pvtuner_dominant_seventh_chord( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.25; pitchgrid[2] = pbase * 1.5; pitchgrid[3] = pbase * 1.781797; scale_steps = 4 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = DOMINANT_SEVENTH_CHORD; x->scale_steps = scale_steps; } void pvtuner_eq8( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.090508; pitchgrid[2] = pbase * 1.189207; pitchgrid[3] = pbase * 1.296840; pitchgrid[4] = pbase * 1.414214; pitchgrid[5] = pbase * 1.542211; pitchgrid[6] = pbase * 1.681793; pitchgrid[7] = pbase * 1.834008; scale_steps = 8 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = EQ8; x->scale_steps = scale_steps; } void pvtuner_pentaclust( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.059463; pitchgrid[2] = pbase * 1.122462; pitchgrid[3] = pbase * 1.189207; pitchgrid[4] = pbase * 1.259921; scale_steps = 5 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = PENTACLUST; x->scale_steps = scale_steps; } void pvtuner_quarterclust( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.029302; pitchgrid[2] = pbase * 1.059463; pitchgrid[3] = pbase * 1.090508; pitchgrid[4] = pbase * 1.122462; pitchgrid[5] = pbase * 1.155353; pitchgrid[6] = pbase * 1.189207; pitchgrid[7] = pbase * 1.224054; scale_steps = 8 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = QUARTERCLUST; x->scale_steps = scale_steps; } void pvtuner_eq5( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.148698; pitchgrid[2] = pbase * 1.319508; pitchgrid[3] = pbase * 1.515717; pitchgrid[4] = pbase * 1.741101; scale_steps = 5 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = EQ5; x->scale_steps = scale_steps; } void pvtuner_pelog( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.152; pitchgrid[2] = pbase * 1.340; pitchgrid[3] = pbase * 1.532; pitchgrid[4] = pbase * 1.756; scale_steps = 5 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = PELOG; x->scale_steps = scale_steps; } void pvtuner_slendro( t_pvtuner *x ){ int i, j; float *pitchgrid = x->pitchgrid; float pbase = x->pbase; int scale_steps; pitchgrid[0] = pbase; pitchgrid[1] = pbase * 1.104; pitchgrid[2] = pbase * 1.199; pitchgrid[3] = pbase * 1.404; pitchgrid[4] = pbase * 1.514; pitchgrid[5] = pbase * 1.615; pitchgrid[6] = pbase * 1.787; scale_steps = 7 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < scale_steps; j++ ){ pitchgrid[ i * scale_steps + j] = pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = SLENDRO; x->scale_steps = scale_steps; } void pvtuner_eastern( t_pvtuner *x ){ int i, j; x->pitchgrid[0] = x->pbase; x->pitchgrid[1] = x->pbase * 1.059463; x->pitchgrid[2] = x->pbase * 1.259921; x->pitchgrid[3] = x->pbase * 1.334840; x->pitchgrid[4] = x->pbase * 1.498307; x->pitchgrid[5] = x->pbase * 1.587401; x->pitchgrid[6] = x->pbase * 1.887749; x->scale_steps = 7 ; for( i = 1; i < 10; i++ ){ for( j = 0; j < x->scale_steps; j++ ){ x->pitchgrid[ i*x->scale_steps + j] = x->pitchgrid[j] * pow(2.0,(float)i); } } x->current_scale = EASTERN ; // post("eastern scale"); } #if MSP void pvtuner_float(t_pvtuner *x, double f) { // int inlet = ((t_pxobject*)x)->z_in; int inlet = x->x_obj.z_in; if (inlet == 1) { x->P = f; x->myPInc = x->P*x->L/x->R; // post("P set to %f",f); } else if (inlet == 2) { x->synt = f; // post("synt set to %f",f); } } #endif float closestf(float test, float *arr) { int i; i = 0; if( test <= arr[0] ){ return arr[0]; } while( i < MAXTONES ){ if( arr[i] > test ){ break; } ++i; } if( i >= MAXTONES - 1) { return arr[MAXTONES - 1]; } if( (test - arr[i-1]) > ( arr[i] - test) ) { return arr[i]; } else { return arr[i-1]; } } void pvtuner_bypass(t_pvtuner *x, t_floatarg state) { x->bypass_state = state; } void pvtuner_mute(t_pvtuner *x, t_floatarg state) { x->mute = state; // post("mute: %d", state); } void pvtuner_overlap(t_pvtuner *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; pvtuner_init(x,1); } void pvtuner_winfac(t_pvtuner *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; pvtuner_init(x,2); } void pvtuner_fftinfo(t_pvtuner *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void pvtuner_dsp(t_pvtuner *x, t_signal **sp, short *count) { #if MSP x->pitch_connected = count[1]; x->synt_connected = count[2]; #endif #if PD x->pitch_connected = 1; x->synt_connected = 1; #endif if(sp[0]->s_n != x->vs || x->R != sp[0]->s_sr ){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; pvtuner_init(x,1); } dsp_add(pvtuner_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } #if MSP void main(void) { setup((t_messlist **)&pvtuner_class, (method)pvtuner_new, (method)pvtuner_free, (short)sizeof(t_pvtuner), 0, A_GIMME, 0); addmess((method)pvtuner_dsp, "dsp", A_CANT, 0); addmess((method)pvtuner_assist,"assist",A_CANT,0); addmess((method)pvtuner_bypass,"bypass",A_DEFFLOAT,0); addmess((method)pvtuner_mute,"mute",A_DEFFLOAT,0); addmess((method)pvtuner_basefreq,"basefreq",A_DEFFLOAT,0); addmess((method)pvtuner_diatonic,"diatonic",0); addmess((method)pvtuner_eastern,"eastern",0); addmess((method)pvtuner_minor,"minor",0); addmess((method)pvtuner_eq12,"eq12",0); addmess((method)pvtuner_pentatonic,"pentatonic",0); addmess((method)pvtuner_major_added_sixth,"added_sixth_major",0); addmess((method)pvtuner_minor_added_sixth,"added_sixth_minor",0); addmess((method)pvtuner_major_seventh_chord,"major_seventh_chord",0); addmess((method)pvtuner_minor_seventh_chord,"minor_seventh_chord",0); addmess((method)pvtuner_dominant_seventh_chord,"dominant_seventh_chord",0); addmess((method)pvtuner_eq8,"eq8",0); addmess((method)pvtuner_pentaclust,"pentaclust",0); addmess((method)pvtuner_quarterclust,"quarterclust",0); addmess((method)pvtuner_eq5,"eq5",0); addmess((method)pvtuner_slendro,"slendro",0); addmess((method)pvtuner_pelog,"pelog",0); addmess((method)pvtuner_import_scale,"import_scale",A_DEFSYM,0); addmess((method)pvtuner_list,"list",A_GIMME,0); addmess((method)pvtuner_topfreq,"topfreq",A_DEFFLOAT,0); addmess((method)pvtuner_toptune,"toptune",A_DEFFLOAT,0); addmess((method)pvtuner_frequency_range,"frequency_range",A_FLOAT,A_FLOAT, 0); addmess((method)pvtuner_overlap,"overlap",A_DEFFLOAT,0); addmess((method)pvtuner_winfac,"winfac",A_DEFFLOAT,0); addmess((method)pvtuner_fftinfo,"fftinfo",0); addmess((method)pvtuner_binfo,"binfo",0); addfloat((method)pvtuner_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void pvtuner_tilde_setup(void) { pvtuner_class = class_new(gensym("pvtuner~"), (t_newmethod)pvtuner_new, (t_method)pvtuner_free ,sizeof(t_pvtuner), 0,A_GIMME,0); CLASS_MAINSIGNALIN(pvtuner_class, t_pvtuner, x_f ); class_addmethod(pvtuner_class, (t_method)pvtuner_dsp, gensym("dsp"), 0); class_addmethod(pvtuner_class, (t_method)pvtuner_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(pvtuner_class, (t_method)pvtuner_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(pvtuner_class, (t_method)pvtuner_assist, gensym("assist"), 0); class_addmethod(pvtuner_class, (t_method)pvtuner_basefreq,gensym("basefreq"),A_DEFFLOAT,0); class_addmethod(pvtuner_class, (t_method)pvtuner_frequency_range,gensym("frequency_range"),A_DEFFLOAT,A_DEFFLOAT,0); class_addmethod(pvtuner_class, (t_method)pvtuner_diatonic,gensym("diatonic"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_eastern,gensym("eastern"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_minor,gensym("minor"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_eq12,gensym("eq12"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_pentatonic,gensym("pentatonic"),0); /* Pd cannot disambiguate */ /* class_addmethod(pvtuner_class, (t_method)pvtuner_added_sixth_major,gensym("added_sixth_major"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_added_sixth_minor,gensym("added_sixth_minor"),0); */ class_addmethod(pvtuner_class, (t_method)pvtuner_major_added_sixth,gensym("major_added_sixth"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_minor_added_sixth,gensym("minor_added_sixth"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_major_seventh_chord,gensym("major_seventh_chord"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_minor_seventh_chord,gensym("minor_seventh_chord"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_dominant_seventh_chord,gensym("dominant_seventh_chord"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_eq8,gensym("eq8"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_pentaclust,gensym("pentaclust"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_quarterclust,gensym("quarterclust"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_eq5,gensym("eq5"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_slendro,gensym("slendro"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_pelog,gensym("pelog"),0); class_addmethod(pvtuner_class, (t_method)pvtuner_import_scale,gensym("import_scale"),A_DEFSYM,0); class_addmethod(pvtuner_class, (t_method)pvtuner_toptune,gensym("toptune"),A_FLOAT, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_topfreq,gensym("topfreq"),A_FLOAT, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_list,gensym("list"),A_GIMME, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_frequency_range,gensym("frequency_range"),A_FLOAT,A_FLOAT, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_overlap,gensym("overlap"),A_FLOAT, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_winfac,gensym("winfac"),A_FLOAT, 0); class_addmethod(pvtuner_class, (t_method)pvtuner_fftinfo,gensym("fftinfo"), 0); class_addmethod(pvtuner_class, (t_method)pvtuner_binfo,gensym("binfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif fftease-2.5.2.git20121005/pvwarp~-help.pd0000644000076500007650000001033212067450034016200 0ustar hanshans#N canvas 36 232 566 392 10; #N canvas 0 22 462 312 pvwarp-block 0; #X obj 185 146 pvwarp~ 0 4000 4 2; #X obj 185 187 outlet~; #X obj 158 250 block~ 256; #X obj 185 88 inlet~; #X obj 339 83 inlet; #X obj 265 47 inlet; #X obj 283 70 inlet; #X obj 321 52 inlet; #X connect 0 0 1 0; #X connect 3 0 0 0; #X connect 4 0 0 0; #X connect 5 0 0 7; #X connect 6 0 0 8; #X connect 7 0 0 9; #X restore 121 125 pd pvwarp-block; #N canvas 595 467 629 326 messages 0; #X obj 182 294 outlet; #X msg 99 77 bottomfreq \$1; #X floatatom 99 54 5 0 0 0 - - -; #X floatatom 253 68 5 0 0 0 - - -; #X msg 253 87 topfreq \$1; #X msg 301 178 autofunc 0.1 2; #X obj 301 158 loadbang; #X text 254 50 highest freq to synthesize; #X text 98 38 lowest freq; #N canvas 430 531 673 333 init 0; #X msg 66 47 automate 1; #X obj 66 17 loadbang; #X text 159 28 this tells Pd to ignore its control inlets and take the warp function exclusively from its internally generated states. This is because otherwise we'd have to deal with sending lots of data to the inlets.; #X text 78 125 FYI - the inlets are as follows: signal in \, CF1 \, BW1 \, warpfac1 \, CF2 \, BW2 \, warpfac2 \, transposition \, synthesis threshold.; #X obj 22 268 outlet; #X obj 196 265 s warp-offset; #X obj 305 262 s warp-transpose; #X obj 429 262 s warp-threshold; #X obj 207 221 unpack f f f; #X msg 207 197 0 1 1e-05; #X obj 207 174 loadbang; #X connect 0 0 4 0; #X connect 1 0 0 0; #X connect 8 0 5 0; #X connect 8 1 6 0; #X connect 8 2 7 0; #X connect 9 0 8 0; #X connect 10 0 9 0; #X restore 290 231 pd init; #X obj 256 26 hsl 128 15 500 5000 0 0 empty empty empty -2 -6 0 8 -260204 -1 -1 8700 1; #X obj 102 17 hsl 128 15 0 1000 0 0 empty empty empty -2 -6 0 8 -260204 -1 -1 0 1; #X text 407 177 punch for a new warp function.; #X text 295 201 parameters are minimum warp and maximum warp.; #X obj 370 259 fftease-system; #X connect 1 0 0 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 5 0; #X connect 9 0 0 0; #X connect 10 0 3 0; #X connect 11 0 2 0; #X connect 14 0 0 0; #X restore 258 109 pd messages; #X msg 44 193 \; pd dsp \$1; #X obj 44 174 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1 ; #X obj 121 160 dac~; #X floatatom 171 89 5 0 0 0 - transpose -; #X floatatom 146 72 5 0 0 0 - offset -; #X obj 201 196 hsl 128 15 0 1 0 0 offset empty offset -2 -6 0 8 -260204 -1 -1 4200 1; #X obj 202 231 hsl 128 15 0.25 1.5 0 0 transpose empty transpose -2 -6 0 8 -260204 -1 -1 7720 1; #X obj 201 264 hsl 128 15 0 0.05 0 0 threshold empty threshold -2 -6 0 8 -260204 -1 -1 0 1; #X floatatom 196 106 5 0 0 0 - threshold -; #X text 231 41 load a sound \, then warp away; #X text 339 262 synthesis threshold; #X text 334 196 offset for warping function; #X text 343 107 <- more info here; #N canvas 639 439 647 498 sound-source 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array pvwarp-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ pvwarp-sound1; #X msg 31 177 read -resize \$1 pvwarp-sound1; #X connect 2 0 13 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 5 0; #X connect 12 1 7 0; #X connect 13 0 1 0; #X restore 121 41 pd sound-source; #X text 80 304 Experimental spectrum warper. An internal frequency warping function is created either according to specification or with the autofunc message. Try it on vocal sounds.; #N canvas 0 22 454 304 rinit 0; #X obj 26 83 r warp-offset; #X obj 135 80 r warp-transpose; #X obj 256 79 r warp-threshold; #X obj 48 160 outlet; #X obj 109 171 outlet; #X obj 244 174 outlet; #X connect 0 0 3 0; #X connect 1 0 4 0; #X connect 2 0 5 0; #X restore 131 231 pd rinit; #X connect 0 0 4 0; #X connect 0 0 4 1; #X connect 1 0 0 4; #X connect 3 0 2 0; #X connect 5 0 0 2; #X connect 6 0 0 1; #X connect 10 0 0 3; #X connect 15 0 0 0; #X connect 17 0 7 0; #X connect 17 1 8 0; #X connect 17 2 9 0; fftease-2.5.2.git20121005/pvwarp~.c0000644000076500007650000005047112067450034015101 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *pvwarp_class; #endif #if PD static t_class *pvwarp_class; #endif #define OBJECT_NAME "pvwarp~" typedef struct _pvwarp { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; float P; int L; int first; float Iinv; float *lastamp; float *lastfreq; float *windex; float *table; float myPInc; float ffac; // int lo_bin; int hi_bin; float lofreq;//user speficied lowest synthfreq float hifreq;// user specified highest synthfreq float topfreq; float synt; float myPI; float TWOmyPI; // for fast fft float mult; float *trigland; int *bitshuffle; // short *connections; short mute; short bypass; int pitch_connected; int synt_connected; float *warpfunc ; short please_update; short always_update; float cf1; float bw1; float warpfac1; float cf2; float bw2; float warpfac2; int funcoff; short verbose; short automate; int overlap;//overlap factor int winfac;// window factor int vs;//last measurement of vector size } t_pvwarp; void *pvwarp_new(t_symbol *s, int argc, t_atom *argv); //t_int *offset_perform(t_int *w); t_int *pvwarp_perform(t_int *w); void pvwarp_dsp(t_pvwarp *x, t_signal **sp, short *count); void pvwarp_assist(t_pvwarp *x, void *b, long m, long a, char *s); void pvwarp_bypass(t_pvwarp *x, t_floatarg state); void pvwarp_mute(t_pvwarp *x, t_floatarg state); void pvwarp_verbose(t_pvwarp *x, t_floatarg state); void pvwarp_overlap(t_pvwarp *x, t_floatarg o); void pvwarp_automate(t_pvwarp *x, t_floatarg state); void pvwarp_autofunc(t_pvwarp *x, t_floatarg minval, t_floatarg maxval); void pvwarp_float(t_pvwarp *x, t_float f); void pvwarp_dsp_free( t_pvwarp *x ); void pvwarp_fftinfo( t_pvwarp *x ); float myrand( float min, float max ); float closestf(float test, float *arr) ; int freq_to_bin( float target, float fundamental ); void update_warp_function( t_pvwarp *x ) ; void pvwarp_init(t_pvwarp *x, short initialized); void pvwarp_bottomfreq(t_pvwarp *x, t_floatarg f); void pvwarp_topfreq(t_pvwarp *x, t_floatarg f); void pvwarp_fftinfo(t_pvwarp *x); void pvwarp_overlap(t_pvwarp *x, t_floatarg f); void pvwarp_winfac(t_pvwarp *x, t_floatarg f);; #if MSP void main(void) { setup((t_messlist **)&pvwarp_class, (method)pvwarp_new, (method)pvwarp_dsp_free, (short)sizeof(t_pvwarp), 0, A_GIMME, 0); addmess((method)pvwarp_dsp, "dsp", A_CANT, 0); addmess((method)pvwarp_assist,"assist",A_CANT,0); addmess((method)pvwarp_bypass,"bypass",A_DEFFLOAT,0); addmess((method)pvwarp_mute,"mute",A_DEFFLOAT,0); addmess((method)pvwarp_verbose,"verbose",A_DEFFLOAT,0); addmess((method)pvwarp_overlap,"overlap",A_FLOAT,0); addmess((method)pvwarp_bottomfreq,"bottomfreq",A_FLOAT,0); addmess((method)pvwarp_topfreq,"topfreq",A_FLOAT,0); addmess((method)pvwarp_fftinfo,"fftinfo",0); addmess((method)pvwarp_autofunc,"autofunc",A_DEFFLOAT, A_DEFFLOAT,0); addmess((method)pvwarp_overlap,"overlap",A_DEFFLOAT,0); addmess((method)pvwarp_winfac,"winfac",A_DEFFLOAT,0); addmess((method)pvwarp_fftinfo,"fftinfo",0); addfloat((method)pvwarp_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD /* Pd Initialization */ void pvwarp_tilde_setup(void) { pvwarp_class = class_new(gensym("pvwarp~"), (t_newmethod)pvwarp_new, (t_method)pvwarp_dsp_free ,sizeof(t_pvwarp), 0,A_GIMME,0); CLASS_MAINSIGNALIN(pvwarp_class, t_pvwarp, x_f); class_addmethod(pvwarp_class, (t_method)pvwarp_dsp, gensym("dsp"), 0); class_addmethod(pvwarp_class, (t_method)pvwarp_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(pvwarp_class, (t_method)pvwarp_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(pvwarp_class, (t_method)pvwarp_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(pvwarp_class, (t_method)pvwarp_bottomfreq, gensym("bottomfreq"), A_DEFFLOAT,0); class_addmethod(pvwarp_class, (t_method)pvwarp_topfreq, gensym("topfreq"), A_DEFFLOAT, 0); class_addmethod(pvwarp_class, (t_method)pvwarp_automate, gensym("automate"), A_DEFFLOAT, 0); class_addmethod(pvwarp_class, (t_method)pvwarp_autofunc, gensym("autofunc"), A_DEFFLOAT,A_DEFFLOAT,0); class_addmethod(pvwarp_class,(t_method)pvwarp_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(pvwarp_class,(t_method)pvwarp_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(pvwarp_class,(t_method)pvwarp_fftinfo,gensym("fftinfo"),0); // addfloat((method)pvwarp_float); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void pvwarp_automate(t_pvwarp *x, t_floatarg state) { x->automate = state; } void pvwarp_overlap(t_pvwarp *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; pvwarp_init(x,1); } void pvwarp_winfac(t_pvwarp *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; pvwarp_init(x,2); } void pvwarp_fftinfo(t_pvwarp *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } float myrand ( float min, float max ) { return (min + (max-min) * ((float) (rand() % 32768) / (float) 32768.0)); } void update_warp_function( t_pvwarp *x ) { int i,j; int N2 = x->N2; float *warpfunc = x->warpfunc; float warpfac1 = x->warpfac1; float warpfac2 = x->warpfac2; float cf1 = x->cf1; float cf2 = x->cf2; float bw1 = x->bw1; float bw2 = x->bw2; float c_fundamental = x->c_fundamental; float deviation; float diff; int midbin, lobin, hibin ; float hif, lof; int bin_extent; short verbose = x->verbose; for( i = 0; i < N2; i++ ){ warpfunc[i] = 1.0; } hif = cf1 * (1. + bw1); lof = cf1 * (1. - bw1); midbin = freq_to_bin( cf1, c_fundamental ); hibin = freq_to_bin( hif, c_fundamental ); lobin = freq_to_bin( lof, c_fundamental ); if( hibin >= N2 - 1 ){ hibin = N2 - 1; } if( lobin < 0 ){ lobin = 0; } if( verbose ) post("bump1: hi %d mid %d lo %d",hibin,midbin,lobin); warpfunc[midbin] = warpfac1; diff = warpfac1 - 1.0 ; bin_extent = hibin - midbin ; for( i = midbin, j = 0; i < hibin; i++, j++ ){ deviation = diff * ((float)(bin_extent - j) / (float) bin_extent ); warpfunc[ i ] += deviation ; } bin_extent = midbin - lobin ; for( i = midbin, j = 0; i > lobin; i--, j++ ){ deviation = diff * ((float)(bin_extent - j) / (float) bin_extent ); warpfunc[ i ] += deviation ; } // NOW DO SECOND BUMP hif = cf2 * (1. + bw2); lof = cf2 * (1. - bw2); midbin = freq_to_bin( cf2, c_fundamental ); hibin = freq_to_bin( hif, c_fundamental ); lobin = freq_to_bin( lof, c_fundamental ); if( hibin >= N2 - 1 ){ hibin = N2 - 1; } if( lobin < 0 ){ lobin = 0; } if( verbose ) post("bump2: hi %d mid %d lo %d",hibin,midbin,lobin); warpfunc[midbin] = warpfac2; diff = warpfac2 - 1.0 ; bin_extent = hibin - midbin ; for( i = midbin, j = 0; i < hibin; i++, j++ ){ deviation = diff * ((float)(bin_extent - j) / (float) bin_extent ); warpfunc[ i ] += deviation ; } bin_extent = midbin - lobin ; for( i = midbin, j = 0; i > lobin; i--, j++ ){ deviation = diff * ((float)(bin_extent - j) / (float) bin_extent ); warpfunc[ i ] += deviation ; } x->please_update = 0; // return( x ); } void pvwarp_verbose(t_pvwarp *x, t_floatarg state) { x->verbose = state; } void pvwarp_autofunc(t_pvwarp *x, t_floatarg minval, t_floatarg maxval) { int minpoints, maxpoints, segpoints, i; int pointcount = 0; float target, lastval; float m1, m2; int N2 = x->N2; float *warpfunc = x->warpfunc; ///// minpoints = 0.05 * (float) N2; maxpoints = 0.25 * (float) N2; if( minval > 1000.0 || minval < .001 ){ minval = 0.5; } if( maxval < 0.01 || maxval > 1000.0 ){ minval = 2.0; } lastval = myrand(minval, maxval); // post("automate: min %d max %d",minpoints, maxpoints); while( pointcount < N2 ){ target = myrand(minval, maxval); segpoints = minpoints + (rand() % (maxpoints-minpoints)); if( pointcount + segpoints > N2 ){ segpoints = N2 - pointcount; } for( i = 0; i < segpoints; i++ ){ m2 = (float)i / (float) segpoints ; m1 = 1.0 - m2; warpfunc[ pointcount + i ] = m1 * lastval + m2 * target; } lastval = target; pointcount += segpoints; } } void pvwarp_bypass(t_pvwarp *x, t_floatarg state) { x->bypass = state; } void pvwarp_mute(t_pvwarp *x, t_floatarg state) { x->mute = state; } void pvwarp_dsp_free( t_pvwarp *x ){ #if MSP dsp_free( (t_pxobject *) x); #endif free(x->c_lastphase_in); free(x->c_lastphase_out); free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->input); free(x->Hwin); free(x->buffer); free(x->channel); free(x->output); free(x->lastamp); free(x->lastfreq); free(x->windex); free(x->table); free(x->warpfunc); free(x->connections); } void pvwarp_assist (t_pvwarp *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input "); break; case 1: sprintf(dst,"(signal/float) Center Frequency 1"); break; case 2: sprintf(dst,"(signal/float) Bandwidth Factor 1"); break; case 3: sprintf(dst,"(signal/float) Warp Factor 1"); break; case 4: sprintf(dst,"(signal/float) Center Frequency 2"); break; case 5: sprintf(dst,"(signal/float) Bandwidth Factor 2"); break; case 6: sprintf(dst,"(signal/float) Warp Factor 2"); break; case 7: sprintf(dst,"(signal/float) Function Offset (0.0-1.0) "); break; case 8: sprintf(dst,"(signal/float) Pitch Factor"); break; case 9: sprintf(dst,"(signal/float) Synthesis Gate Value"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void *pvwarp_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_pvwarp *x = (t_pvwarp *)newobject(pvwarp_class); dsp_setup((t_pxobject *)x,10); outlet_new((t_pxobject *)x, "signal"); #endif #if PD int i; t_pvwarp *x = (t_pvwarp *)pd_new(pvwarp_class); for(i=0;i<9;i++) inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->lofreq = atom_getfloatarg(0,argc,argv); x->hifreq = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); if(!x->overlap) x->overlap = 4; if(!x->winfac) x->winfac = 2; x->D = sys_getblksize(); x->R = sys_getsr(); pvwarp_init(x,0); return (x); } void pvwarp_init(t_pvwarp *x, short initialized) { int i, j; float funda, curfreq; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->c_fundamental = (float) x->R/(float)( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->Iinv = 1./x->D; x->myPInc = x->P*x->L/x->R;// really needed x->ffac = x->P * PI/x->N; if(!initialized){ srand(clock()); x->L = 8192; x->P = 1.0 ; //initialization only x->please_update = 0; x->verbose = 0; x->bypass = 0; x->mute = 0; x->topfreq = 3000. ; x->always_update = 0; x->automate = 0; x->warpfac1 = 1.0; x->warpfac2 = 1.0; x->funcoff = 0; x->cf1 = 500.; x->cf2 = 3000.; x->bw1 = 0.2; x->bw2 = 0.2; x->synt = .000001; x->connections = (short *) calloc(16, sizeof(short)); x->Wanal = (float *) calloc(MAX_Nw, sizeof(float)); x->Wsyn = (float *) calloc(MAX_Nw, sizeof(float)); x->input = (float *) calloc(MAX_Nw, sizeof(float)); x->Hwin = (float *) calloc(MAX_Nw, sizeof(float)); x->buffer = (float *) calloc(MAX_N, sizeof(float)); x->channel = (float *) calloc(MAX_N+2, sizeof(float)); x->output = (float *) calloc(MAX_Nw, sizeof(float)); x->bitshuffle = (int *) calloc(MAX_N * 2, sizeof(int)); x->trigland = (float *) calloc(MAX_N * 2, sizeof(float)); x->warpfunc = (float *) calloc(MAX_N2, sizeof(float)); x->lastamp = (float *) calloc(MAX_N+1, sizeof(float)); x->lastfreq = (float *) calloc(MAX_N+1, sizeof(float)); x->windex = (float *) calloc(MAX_N+1, sizeof(float)); x->table = (float *) calloc(x->L, sizeof(float)); x->c_lastphase_in = (float *) calloc(MAX_N2+1, sizeof(float)); x->c_lastphase_out = (float *) calloc(MAX_N2+1, sizeof(float)); } for (i = 0; i < x->L; i++) { x->table[i] = (float) x->N * cos((float)i * TWOPI / (float)x->L); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->buffer,0,x->N * sizeof(float)); memset((char *)x->channel,0,(x->N+2) * sizeof(float)); memset((char *)x->lastfreq,0,(x->N+1) * sizeof(float)); memset((char *)x->lastamp,0,(x->N+1) * sizeof(float)); // added memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); memset((char *)x->windex,0,(x->N+1) * sizeof(float)); if( x->hifreq < x->c_fundamental ) { x->hifreq = 1000.0;// arbitrary } x->hi_bin = 1; curfreq = 0; while( curfreq < x->hifreq ) { ++(x->hi_bin); curfreq += x->c_fundamental ; } if( x->hi_bin >= x->N2 ) x->hi_bin = x->N2 - 1; x->lo_bin = 0; curfreq = 0; while( curfreq < x->lofreq ) { ++(x->lo_bin); curfreq += x->c_fundamental ; } update_warp_function(x); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); // post("FFT size: %d",x->N); } void pvwarp_bottomfreq(t_pvwarp *x, t_floatarg f) { int tbin; float curfreq; float fundamental = x->c_fundamental; tbin = 1; curfreq = 0; if( f < 0 || f > x->R / 2.0 ){ error("frequency %f out of range", f); return; } while( curfreq < f ) { ++tbin; curfreq += fundamental ; } if( tbin < x->hi_bin && tbin >= 0 ){ x->lo_bin = tbin; x->lofreq = f; } else { error("bin %d out of range", tbin); } } void pvwarp_topfreq(t_pvwarp *x, t_floatarg f) { int tbin; float curfreq; float fundamental = x->c_fundamental; tbin = 1; curfreq = 0; if( f < 0 || f > x->R / 2.0 ){ error("frequency %f out of range", f); return; } while( curfreq < f ) { ++tbin; curfreq += fundamental ; } if( tbin > x->lo_bin && tbin < x->N2 - 1 ){ x->hi_bin = tbin; x->hifreq = f; } else { error("bin %d out of range", tbin); } } t_int *pvwarp_perform(t_int *w) { int i,j, in,on; int amp,freq,chan,NP,L = 8192; float a,ainc,f,finc,address; int breaker = 0; t_pvwarp *x = (t_pvwarp *) (w[1]); t_float *inbuf = (t_float *)(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 *in4 = (t_float *)(w[6]); t_float *in5 = (t_float *)(w[7]); t_float *in6 = (t_float *)(w[8]); t_float *in7 = (t_float *)(w[9]); t_float *in8 = (t_float *)(w[10]); t_float *in9 = (t_float *)(w[11]); t_float *outbuf = (t_float *)(w[12]); t_int n = w[13]; int D = x->D; int I = D; int R = x->R; int Nw = x->Nw; int N = x->N ; int N2 = x-> N2; int Nw2 = x->Nw2; float fundamental = x->c_fundamental; float factor_in = x->c_factor_in; float factor_out = x->c_factor_out; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; float warpfac1 = x->warpfac1; float warpfac2 = x->warpfac2; int funcoff; float P; float synt; float Iinv = 1./x->D; float myPInc = x->myPInc; /* assign pointers */ float *table = x->table; float *lastamp = x->lastamp ; float *lastfreq = x->lastfreq ; float *windex = x->windex; float *lastphase_in = x->c_lastphase_in; float *lastphase_out = x->c_lastphase_out; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *Hwin = x->Hwin; float *buffer = x->buffer; float *channel = x->channel; float *output = x->output; short *connections = x->connections; float *warpfunc; int hi_bin = x->hi_bin; int lo_bin = x->lo_bin; if(!x->automate) { if( connections[0] ) { x->cf1 = *in1 ; } if ( connections[1] ) { x->bw1 = *in2 ; } if ( connections[2] ) { x->warpfac1 = *in3 ; } if( connections[3] ) { x->cf2 = *in4 ; } if ( connections[4] ) { x->bw2 = *in5 ; } if ( connections[5] ) { x->warpfac2 = *in6 ; } } if( connections[6] ) { f = *in7 ; if( f < 0 ) { f = 0.0; } else if (f > 1.0 ){ f = 1.0; } x->funcoff = f * (float) (N2 - 1); } if ( connections[7] ) { x->P = *in8 ; x->myPInc = x->P*x->L/x->R; } if ( connections[8] ) { x->synt = *in9 ; } P= x->P; synt = x->synt; funcoff = x->funcoff; if( (x->please_update || x->always_update) && ! x->automate){ update_warp_function(x); } warpfunc = x->warpfunc; in = on = x->inCount ; if( x->mute) { for ( j = 0; j < n; j++ ){ outbuf[j] = 0.; } return (w+14); } else if( x->bypass ) { for ( j = 0; j < n; j++ ){ outbuf[j] = *inbuf++; } return (w+14); } else { in = on = x->inCount ; in += D; on += I; for ( j = 0 ; j < (Nw - D) ; j++ ){ input[j] = input[j+D]; } for ( j = (Nw-D), i = 0 ; j < Nw; j++, i++ ) { input[j] = *inbuf++; } fold( input, Wanal, Nw, buffer, N, in ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, lastphase_in, fundamental, factor_in ); // start osc bank for ( chan = lo_bin; chan < hi_bin; chan++ ) { freq = ( amp = ( chan << 1 ) ) + 1; if ( channel[amp] < synt ){ breaker = 1; } if( breaker ) { breaker = 0 ; } else { /* HERE IS WHERE WE WARP THE SPECTRUM */ channel[freq] *= myPInc * warpfunc[(chan + funcoff) % N2]; finc = ( channel[freq] - ( f = lastfreq[chan] ) )*Iinv; ainc = ( channel[amp] - ( a = lastamp[chan] ) )*Iinv; address = windex[chan]; for ( n = 0; n < I; n++ ) { output[n] += a*table[ (int) address ]; address += f; while ( address >= L ) address -= L; while ( address < 0 ) address += L; a += ainc; f += finc; } lastfreq[chan] = channel[freq]; lastamp[chan] = channel[amp]; windex[chan] = address; } } for ( j = 0; j < D; j++ ){ *outbuf++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } /* restore state variables */ x->inCount = in % Nw; return (w+14); } } int freq_to_bin( float target, float fundamental ){ float lastf = 0.0; float testf = 0.0; int thebin = 0; while( testf < target ){ ++thebin; lastf = testf; testf += fundamental; } if(fabs(target - testf) < fabs(target - lastf) ){ return thebin; } else { return (thebin - 1); } } #if MSP void pvwarp_float(t_pvwarp *x, t_float f) // Look at floats at inlets { int inlet = ((t_pxobject*)x)->z_in; int N2 = x->N2; if (inlet == 1){ x->cf1 = f; x->please_update = 1; } else if (inlet == 2) { x->bw1 = f; x->please_update = 1; } else if (inlet == 3) { x->warpfac1 = f; x->please_update = 1; } else if (inlet == 4) { x->cf2 = f; x->please_update = 1; } else if (inlet == 5) { x->bw2 = f; x->please_update = 1; } else if (inlet == 6) { x->warpfac2 = f; x->please_update = 1; } else if (inlet == 7) { if( f < 0 ) { f = 0.0; } else if (f > 1.0 ){ f = 1.0; } x->funcoff = f * (float) (x->N2 - 1); } else if (inlet == 8) { x->P = f; x->myPInc = x->P*x->L/x->R; } else if (inlet == 9) { x->synt = f; } } #endif void pvwarp_dsp(t_pvwarp *x, t_signal **sp, short *count) { long i; x->always_update = 0; #if MSP for( i = 1; i < 10; i++ ){ // only the first 6 inlets alter warp function if( i < 6 ){ x->always_update += count[i]; } x->connections[i-1] = count[i]; // post("connection %d: %d", i-1, count[i]); } #endif #if PD x->always_update = 1; for(i=0;i<10;i++){ x->connections[i] = 1; } #endif if(x->D != sp[0]->s_n || x->R != sp[0]->s_sr){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; pvwarp_init(x,1); } dsp_add(pvwarp_perform, 13, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[6]->s_vec, sp[7]->s_vec, sp[8]->s_vec, sp[9]->s_vec, sp[10]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/qsortE.c0000644000076500007650000002062212067450034014634 0ustar hanshans/* Plug-compatible replacement for UNIX qsort. Copyright (C) 1989 Free Software Foundation, Inc. Written by Douglas C. Schmidt (schmidt@ics.uci.edu) This file is part of GNU CC. GNU QSORT is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU QSORT is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU QSORT; see the file COPYING. If not, write to the Free the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Synched up with: FSF 19.28. */ #ifdef sparc #include #endif #include /* Invoke the comparison function, returns either 0, < 0, or > 0. */ #define CMP(A,B) ((*cmp)((A),(B))) /* Byte-wise swap two items of size SIZE. */ #define SWAP(A,B,SIZE) do {int sz = (SIZE); char *a = (A); char *b = (B); \ do { char _temp = *a;*a++ = *b;*b++ = _temp;} while (--sz);} while (0) /* Copy SIZE bytes from item B to item A. */ #define COPY(A,B,SIZE) {int sz = (SIZE); do { *(A)++ = *(B)++; } while (--sz); } /* This should be replaced by a standard ANSI macro. */ #define BYTES_PER_WORD 8 /* The next 4 #defines implement a very fast in-line stack abstraction. */ #define STACK_SIZE (BYTES_PER_WORD * sizeof (long)) #define PUSH(LOW,HIGH) do {top->lo = LOW;top++->hi = HIGH;} while (0) #define POP(LOW,HIGH) do {LOW = (--top)->lo;HIGH = top->hi;} while (0) #define STACK_NOT_EMPTY (stack < top) /* Discontinue quicksort algorithm when partition gets below this size. This particular magic number was chosen to work best on a Sun 4/260. */ #define MAX_THRESH 4 /* requisite prototype */ int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)()); /* Stack node declarations used to store unfulfilled partition obligations. */ typedef struct { char *lo; char *hi; } stack_node; /* Order size using quicksort. This implementation incorporates four optimizations discussed in Sedgewick: 1. Non-recursive, using an explicit stack of pointer that store the next array partition to sort. To save time, this maximum amount of space required to store an array of MAX_INT is allocated on the stack. Assuming a 32-bit integer, this needs only 32 * sizeof (stack_node) == 136 bits. Pretty cheap, actually. 2. Choose the pivot element using a median-of-three decision tree. This reduces the probability of selecting a bad pivot value and eliminates certain extraneous comparisons. 3. Only quicksorts TOTAL_ELEMS / MAX_THRESH partitions, leaving insertion sort to order the MAX_THRESH items within each partition. This is a big win, since insertion sort is faster for small, mostly sorted array segments. 4. The larger of the two sub-partitions is always pushed onto the stack first, with the algorithm then concentrating on the smaller partition. This *guarantees* no more than log (n) stack size is needed (actually O(1) in this case)! */ int qsortE (char *base_ptr, int total_elems, int size, int (*cmp)()) { /* Allocating SIZE bytes for a pivot buffer facilitates a better algorithm below since we can do comparisons directly on the pivot. */ char *pivot_buffer = (char *) malloc(size); int max_thresh = MAX_THRESH * size; if (total_elems > MAX_THRESH) { char *lo = base_ptr; char *hi = lo + size * (total_elems - 1); stack_node stack[STACK_SIZE]; /* Largest size needed for 32-bit int!!! */ stack_node *top = stack + 1; while (STACK_NOT_EMPTY) { char *left_ptr; char *right_ptr; { char *pivot = pivot_buffer; { /* Select median value from among LO, MID, and HI. Rearrange LO and HI so the three values are sorted. This lowers the probability of picking a pathological pivot value and skips a comparison for both the LEFT_PTR and RIGHT_PTR. */ char *mid = lo + size * ((hi - lo) / size >> 1); if (CMP (mid, lo) < 0) SWAP (mid, lo, size); if (CMP (hi, mid) < 0) SWAP (mid, hi, size); else goto jump_over; if (CMP (mid, lo) < 0) SWAP (mid, lo, size); jump_over: COPY (pivot, mid, size); pivot = pivot_buffer; } left_ptr = lo + size; right_ptr = hi - size; /* Here's the famous ``collapse the walls'' section of quicksort. Gotta like those tight inner loops! They are the main reason that this algorithm runs much faster than others. */ do { while (CMP (left_ptr, pivot) < 0) left_ptr += size; while (CMP (pivot, right_ptr) < 0) right_ptr -= size; if (left_ptr < right_ptr) { SWAP (left_ptr, right_ptr, size); left_ptr += size; right_ptr -= size; } else if (left_ptr == right_ptr) { left_ptr += size; right_ptr -= size; break; } } while (left_ptr <= right_ptr); } /* Set up pointers for next iteration. First determine whether left and right partitions are below the threshold size. If so, ignore one or both. Otherwise, push the larger partition's bounds on the stack and continue sorting the smaller one. */ if ((right_ptr - lo) <= max_thresh) { if ((hi - left_ptr) <= max_thresh) /* Ignore both small partitions. */ POP (lo, hi); else /* Ignore small left partition. */ lo = left_ptr; } else if ((hi - left_ptr) <= max_thresh) /* Ignore small right partition. */ hi = right_ptr; else if ((right_ptr - lo) > (hi - left_ptr)) /* Push larger left partition indices. */ { PUSH (lo, right_ptr); lo = left_ptr; } else /* Push larger right partition indices. */ { PUSH (left_ptr, hi); hi = right_ptr; } } } /* Once the BASE_PTR array is partially sorted by quicksort the rest is completely sorted using insertion sort, since this is efficient for partitions below MAX_THRESH size. BASE_PTR points to the beginning of the array to sort, and END_PTR points at the very last element in the array (*not* one beyond it!). */ #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) { char *end_ptr = base_ptr + size * (total_elems - 1); char *run_ptr; char *tmp_ptr = base_ptr; char *thresh = MIN (end_ptr, base_ptr + max_thresh); /* Find smallest element in first threshold and place it at the array's beginning. This is the smallest array element, and the operation speeds up insertion sort's inner loop. */ for (run_ptr = tmp_ptr + size; run_ptr <= thresh; run_ptr += size) if (CMP (run_ptr, tmp_ptr) < 0) tmp_ptr = run_ptr; if (tmp_ptr != base_ptr) SWAP (tmp_ptr, base_ptr, size); /* Insertion sort, running from left-hand-side up to `right-hand-side.' Pretty much straight out of the original GNU qsort routine. */ for (run_ptr = base_ptr + size; (tmp_ptr = run_ptr += size) <= end_ptr; ) { while (CMP (run_ptr, tmp_ptr -= size) < 0) ; if ((tmp_ptr += size) != run_ptr) { char *trav; for (trav = run_ptr + size; --trav >= run_ptr;) { char c = *trav; char *hi, *lo; for (hi = lo = trav; (lo -= size) >= tmp_ptr; hi = lo) *hi = *lo; *hi = c; } } } } return 1; } fftease-2.5.2.git20121005/reanimator~-help.pd0000644000076500007650000001274212067450034017031 0ustar hanshans#N canvas 17 365 720 517 10; #N canvas 132 212 480 321 reanimator-block 0; #X obj 15 170 block~ 256; #X obj 19 30 inlet~; #X obj 154 33 inlet~; #X obj 217 34 inlet; #X obj 19 105 outlet~; #X obj 86 105 outlet~; #X obj 154 106 outlet~; #X text 17 128 args: size of texture analysis(ms.) \, overlap factor \, window factor; #X obj 19 78 reanimator~ 5000 4 1; #X connect 1 0 8 0; #X connect 2 0 8 1; #X connect 3 0 8 0; #X connect 8 0 4 0; #X connect 8 1 5 0; #X connect 8 2 6 0; #X restore 96 87 pd reanimator-block; #N canvas 536 186 752 534 driver-sound 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array reanimator-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 reanimator-sound1; #X obj 227 268 tabplay~ reanimator-sound1; #X text 63 132 open the driver sound; #X connect 2 0 11 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 11 0 1 0; #X connect 12 0 5 0; #X connect 12 1 7 0; #X restore 96 30 pd driver-sound; #N canvas 349 43 518 368 texture-sound 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array reanimator-sound2 1.25363e+06 float 2; #X coords 0 1 1.25363e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 reanimator-sound2; #X obj 227 268 tabplay~ reanimator-sound2; #X text 63 132 open the texture sound; #X connect 2 0 11 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 11 0 1 0; #X connect 12 0 5 0; #X connect 12 1 7 0; #X restore 160 49 pd texture-sound; #X msg 499 356 \; pd dsp \$1; #X obj 499 337 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X obj 96 269 dac~; #X obj 160 150 snapshot~; #X floatatom 160 172 5 0 0 0 - - -; #X obj 324 167 snapshot~; #X floatatom 324 189 5 0 0 0 - - -; #X obj 324 134 metro 50; #X obj 324 113 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 324 201 analysis sync; #X text 158 184 matched frame; #N canvas 913 441 569 496 messages 0; #X obj 128 229 outlet; #X msg 24 181 analyze; #X msg 128 117 topbin \$1; #X floatatom 128 81 5 0 0 0 - - -; #X msg 206 117 inverse \$1; #X obj 206 84 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X text 189 163 texture sound must be playing during analysis; #X text 194 183 otherwise: crash!!!; #X text 223 84 matches with *least* good frame; #X text 128 39 top bin to match: lower means less CPU; #X text 128 54 different (perhaps worse) matching; #X obj 36 39 loadbang; #X msg 36 65 20; #X obj 231 213 fftease-system; #N canvas 0 22 454 304 more-info 0; #X text 18 60 How does this work? First load up a texture sound and play it into the right inlet of reanimator~. While the texture sound is playing \, send an "analyze" message and the texture sound will be captured (5 seconds worth in this example patch). Once you see the message "data acquisition completed" in the Pd window \, play any sound into the left inlet and reanimator~ will output the best match from the texture sound. If the input and output are the same sound \, the match should be identical. Otherwise the result is "texture mapping" the texture sound onto the driver sound. The key to effective use of reanimator~ is in smart selections of driver and texture sounds.; #X restore 382 225 pd more-info; #X text 5 163 get texture sample; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 3 0 2 0; #X connect 4 0 0 0; #X connect 5 0 4 0; #X connect 11 0 12 0; #X connect 12 0 3 0; #X connect 13 0 0 0; #X restore 255 71 pd messages; #X text 51 287 reanimator performs spectral reanimation \, AKA audio texture mapping. An online paper descripts this process in greater detail. Essentially reanimator~ captures input from its rightmost inlet and uses this as material to reconstitute sound coming in on the left. Since this is done by searching all stored spectra \, there are limits to how much sound may be recorded before overloading your computer's CPU. Start with a small amount of sound \, say 5 seconds \, and gradually increase until you find your practical limit. Once the texture sound has been recorded \, it may be driven by unlimited amounts of material in the leftmost inlet. Your driver should have a clear rhythmic profile. A drum loop would be a good place to start.; #X text 80 470 http://tinyurl.com/9324v; #X text 57 450 more info below or google "spectral reanimation"; #X text 261 31 <- load sounds into both buffers; #X obj 122 202 hsl 128 15 0 4 0 0 empty empty empty -2 -6 0 8 -176298 -1 -1 11100 1; #X floatatom 119 225 5 0 0 0 - - -; #X obj 96 246 *~ 1; #X text 165 223 gain; #X connect 0 0 21 0; #X connect 0 1 6 0; #X connect 0 2 8 0; #X connect 1 0 0 0; #X connect 2 0 0 1; #X connect 4 0 3 0; #X connect 6 0 7 0; #X connect 8 0 9 0; #X connect 10 0 8 0; #X connect 10 0 6 0; #X connect 11 0 10 0; #X connect 14 0 0 2; #X connect 19 0 20 0; #X connect 20 0 21 1; #X connect 21 0 5 0; #X connect 21 0 5 1; fftease-2.5.2.git20121005/reanimator~.c0000644000076500007650000004514712067450034015727 0ustar hanshans#include "MSPd.h" #include "fftease.h" #define THRESHOLD_MIN (.000001) #if MSP void *reanimator_class; #endif #if PD static t_class *reanimator_class; #endif #define OBJECT_NAME "reanimator~" typedef struct _reanimator { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float **framebank; float *normalized_frame; float current_frame; int framecount; // float frame_increment ; float last_frame ; float fpos; float last_fpos; float tadv; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // faster fft float mult; float *trigland; int *bitshuffle; int read_me; int total_frames; short mute; short initialized; float threshold; short inverse; int top_comparator_bin; short residency_mode; int vs;// vector size int winfac;//window factor int overlap;//overlap factor float sample_len;//duration of texture sample float sync; int megs; } t_reanimator; void *reanimator_new(t_symbol *msg, short argc, t_atom *argv); // t_int *offset_perform(t_int *w); t_int *reanimator_perform(t_int *w); void reanimator_dsp(t_reanimator *x, t_signal **sp, short *count); void reanimator_assist(t_reanimator *x, void *b, long m, long a, char *s); void reanimator_analyze (t_reanimator *x); void reanimator_float(t_reanimator *x, double f) ; void reanimator_mute(t_reanimator *x, t_floatarg flag); void reanimator_inverse(t_reanimator *x, t_floatarg toggle); void reanimator_topbin(t_reanimator *x, t_floatarg bin); void reanimator_startframe(t_reanimator *x, t_floatarg start); void reanimator_endframe(t_reanimator *x, t_floatarg end); void reanimator_framerange(t_reanimator *x, t_floatarg start, t_floatarg end); void reanimator_inverse(t_reanimator *x, t_floatarg toggle); void reanimator_size(t_reanimator *x, t_floatarg size_ms); void reanimator_freeze_and_march(t_reanimator *x, t_floatarg f); void reanimator_resume( t_reanimator *x ); void reanimator_threshold(t_reanimator *x, t_floatarg threshold); void reanimator_dsp_free( t_reanimator *x ); void reanimator_framecount ( t_reanimator *x ); void reanimator_init(t_reanimator *x, short initialized); void reanimator_fftinfo(t_reanimator *x); void reanimator_overlap(t_reanimator *x, t_floatarg f); void reanimator_winfac(t_reanimator *x, t_floatarg f); void reanimator_meminfo(t_reanimator *x); #if MSP void main(void) { setup((t_messlist **)&reanimator_class, (method)reanimator_new, (method)reanimator_dsp_free, (short)sizeof(t_reanimator), 0L, A_GIMME,0); addmess((method)reanimator_dsp, "dsp", A_CANT, 0); addmess((method)reanimator_assist,"assist",A_CANT,0); addfloat((method)reanimator_float); addmess ((method)reanimator_mute, "mute", A_FLOAT, 0); addmess ((method)reanimator_inverse, "inverse", A_FLOAT, 0); addmess ((method)reanimator_topbin, "topbin", A_FLOAT, 0); addmess ((method)reanimator_threshold, "threshold", A_FLOAT, 0); addmess ((method)reanimator_analyze, "analyze", 0); addmess ((method)reanimator_framecount, "framecount", 0); addmess ((method)reanimator_freeze_and_march, "freeze_and_march", A_FLOAT, 0); addmess ((method)reanimator_resume, "resume", 0); addmess((method)reanimator_overlap,"overlap",A_DEFFLOAT,0); addmess((method)reanimator_winfac,"winfac",A_DEFFLOAT,0); addmess((method)reanimator_fftinfo,"fftinfo",0); addmess((method)reanimator_meminfo,"meminfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD /* Pd Initialization */ void reanimator_tilde_setup(void) { reanimator_class = class_new(gensym("reanimator~"), (t_newmethod)reanimator_new, (t_method)reanimator_dsp_free ,sizeof(t_reanimator), 0,A_GIMME,0); CLASS_MAINSIGNALIN(reanimator_class, t_reanimator, x_f); class_addmethod(reanimator_class, (t_method)reanimator_dsp, gensym("dsp"), 0); class_addmethod(reanimator_class, (t_method)reanimator_mute, gensym("mute"), A_FLOAT,0); class_addmethod(reanimator_class, (t_method)reanimator_inverse, gensym("inverse"), A_FLOAT,0); class_addmethod(reanimator_class, (t_method)reanimator_topbin, gensym("topbin"), A_FLOAT,0); class_addmethod(reanimator_class, (t_method)reanimator_threshold, gensym("threshold"), A_FLOAT,0); class_addmethod(reanimator_class, (t_method)reanimator_freeze_and_march, gensym("freeze_and_march"), A_FLOAT, 0); class_addmethod(reanimator_class, (t_method)reanimator_analyze, gensym("analyze"), 0); class_addmethod(reanimator_class, (t_method)reanimator_framecount, gensym("framecount"), 0); class_addmethod(reanimator_class, (t_method)reanimator_overlap, gensym("overlap"), A_FLOAT, 0); class_addmethod(reanimator_class, (t_method)reanimator_winfac, gensym("winfac"), A_FLOAT, 0); class_addmethod(reanimator_class, (t_method)reanimator_fftinfo, gensym("fftinfo"), 0); class_addmethod(reanimator_class, (t_method)reanimator_meminfo, gensym("meminfo"), 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void reanimator_overlap(t_reanimator *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; reanimator_init(x,1); } void reanimator_winfac(t_reanimator *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; reanimator_init(x,2); } void reanimator_meminfo(t_reanimator *x) { post("%s currently stores %d FFT Frames, duration: %f sec., size: %.2f MB", OBJECT_NAME, x->framecount, x->tadv * x->framecount, (float)x->megs/1000000.0); } void reanimator_fftinfo(t_reanimator *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void reanimator_framecount ( t_reanimator *x ) { post("%d frames stored", x->total_frames); } void reanimator_freeze_and_march(t_reanimator *x, t_floatarg f) { x->frame_increment = f; x->residency_mode = 1; } void reanimator_resume( t_reanimator *x ) { x->residency_mode = 0; } void reanimator_dsp_free( t_reanimator *x ){ int i ; #if MSP dsp_free( (t_pxobject *) x); #endif for( i = 0; i < x->framecount; i++ ){ freebytes(x->framebank[i],0) ; } freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->normalized_frame,0); freebytes(x->output,0); } void reanimator_assist (t_reanimator *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Driver Sound "); break; case 1: sprintf(dst,"(signal) Texture Sound"); break; } } else if (msg==2) { switch (arg) { case 0: sprintf(dst,"(signal) Output"); break; case 1: sprintf(dst,"(signal) Matched Frame"); break; case 2: sprintf(dst,"(signal) Sync"); break; } } } void *reanimator_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_reanimator *x = (t_reanimator *)newobject(reanimator_class); dsp_setup((t_pxobject *)x,2); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD int i; t_reanimator *x = (t_reanimator *)pd_new(reanimator_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); for(i=0;i<3;i++) outlet_new(&x->x_obj, gensym("signal")); #endif x->vs = sys_getblksize(); x->R = sys_getsr(); x->sample_len = atom_getfloatarg(0,argc,argv) * .001;// convert to seconds x->overlap = atom_getintarg(1,argc,argv); x->winfac = atom_getintarg(2,argc,argv); if(!x->overlap) x->overlap = 4; if(!x->winfac) x->winfac = 1; if(x->sample_len <= .05){ x->sample_len = 1.0; post("%s: sample length set to default 1000 ms.",OBJECT_NAME); } reanimator_init(x,0); return (x); } void reanimator_init(t_reanimator *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->tadv = (float)x->D/(float)x->R; x->mult = 1. / (float) x->N; x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->current_frame = x->framecount = 0; x->fpos = x->last_fpos = 0; x->framecount = 0; x->total_frames = x->sample_len / x->tadv; if(!initialized){ x->sync = 0.0; x->inverse = 0; x->initialized = 0; x->threshold = .0001; x->top_comparator_bin = 10 ; x->residency_mode = 0; x->frame_increment = 1.0 ; x->mute = 0; x->read_me = 0; x->framecount = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->total_frames = x->sample_len / x->tadv; x->normalized_frame = (float *) getbytes( (MAX_N+2) * sizeof(float)); x->framebank = (float **) getbytes(x->total_frames * sizeof(float *)); /* taking a risk here */ while(x->framecount < x->total_frames ){ x->framebank[(x->framecount)] = (float *) getbytes((x->N+2) * sizeof(float)); memset((char *)x->framebank[(x->framecount)],0,(x->N+2) * sizeof(float)); ++(x->framecount); } } else { while(x->framecount < x->total_frames ){ x->framebank[x->framecount] = (float *) resizebytes((char *)x->framebank[x->framecount],0,(x->N+2) * sizeof(float)); memset((char *)x->framebank[(x->framecount)],0,(x->N+2) * sizeof(float)); ++(x->framecount); } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out =TWOPI * (float) x->D / (float) x->R; init_rdft(x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); x->megs = sizeof(float) * x->framecount * (x->N+2); } t_int *reanimator_perform(t_int *w) { float sample, outsamp ; float ampsum, new_ampsum, rescale; float min_difsum, difsum; int i,j, match_frame=0; ////////////////////////////////////////////// t_reanimator *x = (t_reanimator *) (w[1]); t_float *driver = (t_float *)(w[2]); t_float *texture = (t_float *)(w[3]); t_float *soundout = (t_float *)(w[4]); t_float *matchout = (t_float *)(w[5]); t_float *sync_vec = (t_float *)(w[6]); int n = (int)(w[7]); /* dereference structure */ int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float *normalized_frame = x->normalized_frame; int framecount = x->framecount; int total_frames = x->total_frames; float threshold = x->threshold; int top_comparator_bin = x->top_comparator_bin ; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; float **framebank = x->framebank; // for residency mode float fframe = x->current_frame ; float last_fpos = x->last_fpos ; float fincr = x->frame_increment; float fpos = x->fpos ; float sync = x->sync; /***********************************/ inCount += D; /* SAMPLE MODE */ if( x->read_me ) { for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *texture++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); sync = (float) framecount / (float) total_frames; for ( j = 0; j < n; j++ ){ *sync_vec++ = sync; *matchout++ = 0.0; *soundout++ = 0.0; } convert( buffer, framebank[framecount], N2, c_lastphase_in, c_fundamental, c_factor_in ); new_ampsum = ampsum = 0; for( j = 0; j < N; j+= 2 ){ ampsum += framebank[framecount][j]; } if( ampsum > .00000001 ){ rescale = 1.0 / ampsum ; for( i = 0; i < N; i+= 2 ){ framebank[framecount][i] *= rescale; } ++framecount; } else { post("amplitude for frame %d is too low\n", framecount); } // output empty buffers while reading if( framecount >= total_frames ){ sync = 1.0; x->read_me = 0; // post("reanimator~: data acquisition completed"); x->initialized = 1; // clear input buffer for( i = 0; i < Nw; i++ ) input[i] = 0.0; } } else if (x->mute || ! x->initialized) { for ( j = 0; j < D; j++ ){ *soundout++ = 0.0; *matchout++ = 0.0; *sync_vec++ = sync; } } /* RESIDENCY RESYNTHESIS */ else if( x->residency_mode ) { if( fpos < 0 ) fpos = 0; if( fpos > 1 ) fpos = 1; if( fpos != last_fpos ){ fframe = fpos * (float) framecount ; last_fpos = fpos; } fframe += fincr; while( fframe >= framecount ) { fframe -= framecount; } while( fframe < 0. ) { fframe += framecount ; } unconvert(framebank[(int) fframe ], buffer, N2, c_lastphase_out, c_fundamental, c_factor_out ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount ); for ( j = 0; j < D; j++ ){ *soundout++ = output[j] * mult; *matchout++ = (int) fframe; *sync_vec++ = sync; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } x->current_frame = fframe; x->frame_increment = fincr; x->fpos = fpos; x->sync = sync; } /* REANIMATION HERE */ else { for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *driver++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, c_lastphase_in, c_fundamental, c_factor_in ); ampsum = 0; // NORMALIZE INPUT FRAME for( i = 0; i < N+2; i += 2 ){ ampsum += channel[i]; } if( ampsum > threshold ){ rescale = 1.0 / ampsum; for( i = 0; i < N; i += 2 ){ channel[i] *= rescale; } } else { // AMPLITUDE OF INPUT WAS TOO LOW - OUTPUT SILENCE AND RETURN for ( j = 0; j < D; j++ ){ *soundout++ = 0.0; *matchout++ = 0.0; *sync_vec++ = sync; } x->inCount = inCount; x->sync = sync; return (w+8); } // NOW COMPARE TO STORED FRAMES if( x->inverse ){ // INVERSE CASE min_difsum = 0.0 ; for( j = 0; j < framecount; j++ ){ difsum = 0; for( i = 0; i < top_comparator_bin * 2; i += 2 ){ difsum += fabs( channel[i] - framebank[j][i] ); } // fprintf(stderr,"bin 20: in %f compare %f\n", channel[40], frames[j][40]); if( difsum > min_difsum ){ match_frame = j; min_difsum = difsum; } } } else { // NORMAL CASE min_difsum = 1000000.0 ; for( j = 0; j < framecount; j++ ){ difsum = 0; for( i = 0; i < top_comparator_bin * 2; i += 2 ){ difsum += fabs( channel[i] - framebank[j][i] ); } // fprintf(stderr,"bin 20: in %f compare %f\n", channel[40], frames[j][40]); if( difsum < min_difsum ){ match_frame = j; min_difsum = difsum; } } } unconvert( framebank[match_frame], buffer, N2, c_lastphase_out, c_fundamental, c_factor_out ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount ); // scale back to match for ( j = 0; j < D; j++ ){ *soundout++ = output[j] * (mult / rescale); *matchout++ = (float) match_frame; *sync_vec++ = sync; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } x->current_frame = match_frame; // for residency x->sync = sync; } /* restore state variables */ x->framecount = framecount; x->inCount = inCount % Nw; x->sync = sync; return (w+8); } #if MSP void reanimator_float(t_reanimator *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->frame_increment = f; } else if (inlet == 2) { if (f < 0 ){ f = 0; } else if(f > 1) { f = 1.; } x->fpos = f; } } #endif void reanimator_analyze ( t_reanimator *x ) { // int i, j; x->read_me = 1; x->framecount = 0; // post("reanimator: beginning spectral data acquisition"); return; } void reanimator_mute(t_reanimator *x, t_floatarg flag) { x->mute = flag; // post ("mute set to %d", flag); } void reanimator_topbin(t_reanimator *x, t_floatarg bin) { if( bin > 1 && bin < x->N2 ) x->top_comparator_bin = bin; } void reanimator_inverse(t_reanimator *x, t_floatarg toggle) { x->inverse = toggle; // post ("inverse set to %d", toggle); } void reanimator_threshold(t_reanimator *x, t_floatarg threshold) { if( threshold > THRESHOLD_MIN ) x->threshold = threshold; else x->threshold = THRESHOLD_MIN; } void reanimator_dsp(t_reanimator *x, t_signal **sp, short *count) { // long i; if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; reanimator_init(x,1); } dsp_add(reanimator_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/resent~-help.pd0000644000076500007650000001005712067450034016165 0ustar hanshans#N canvas 309 443 478 328 10; #N canvas 0 22 522 372 sound-source 0; #X text 13 300 try a vocal sound or other sound with strong formant structure; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array resent-sound1 1.25363e+06 float 2; #X coords 0 1 1.25363e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ resent-sound1; #X msg 31 177 read -resize \$1 resent-sound1; #X connect 2 0 13 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 12 0 5 0; #X connect 12 1 7 0; #X connect 13 0 1 0; #X restore 35 68 pd sound-source; #X msg 231 143 \; pd dsp \$1; #X obj 231 117 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #N canvas 0 22 474 324 resent-block 1; #X obj 164 51 inlet~; #X obj 164 143 outlet~; #X obj 271 203 outlet; #X obj 162 183 block~ 256; #X obj 264 54 inlet; #X obj 164 98 resent~ 5000 4 1; #X obj 271 175 snapshot~; #X obj 326 137 metro 50; #X msg 326 116 1; #X obj 326 80 loadbang; #X connect 0 0 5 0; #X connect 4 0 5 0; #X connect 5 0 1 0; #X connect 5 1 6 0; #X connect 6 0 2 0; #X connect 7 0 6 0; #X connect 8 0 7 0; #X connect 9 0 8 0; #X restore 35 114 pd resent-block; #X obj 35 158 dac~; #N canvas 921 180 636 397 messages 0; #X obj 171 295 outlet; #X msg 171 112 acquire_sample; #N canvas 260 436 657 449 global-control 0; #X obj 82 351 outlet; #X msg 257 259 1 0; #X msg 299 259 -1 0; #X text 254 347 set speed and phase; #X msg 82 166 setspeed \$1; #X floatatom 82 140 5 0 0 0 - a -; #X msg 337 259 0 0; #X floatatom 206 66 5 0 0 0 - b -; #X msg 206 92 setphase \$1; #X obj 439 235 vsl 15 128 -2 2 0 0 a empty empty 0 -8 0 8 -236160 -1 -1 0 1; #X obj 461 235 vsl 15 128 0 1 0 0 b empty empty 0 -8 0 8 -236160 -1 -1 0 1; #X msg 257 327 ssap \$1 \$1; #X text 421 209 speed; #X text 460 373 phase; #X connect 1 0 11 0; #X connect 2 0 11 0; #X connect 4 0 0 0; #X connect 5 0 4 0; #X connect 6 0 11 0; #X connect 7 0 8 0; #X connect 8 0 0 0; #X connect 11 0 0 0; #X restore 197 151 pd global-control; #X text 281 112 record sample to FFT buffer; #X obj 320 255 fftease-system; #N canvas 0 22 454 304 init 0; #X msg 158 101 verbose 1; #X obj 158 76 loadbang; #X msg 235 148 playthrough 1; #X obj 235 125 loadbang; #X obj 178 210 outlet; #X connect 0 0 4 0; #X connect 1 0 0 0; #X connect 2 0 4 0; #X connect 3 0 2 0; #X restore 252 245 pd init; #N canvas 786 85 508 405 separate-bin-control 0; #X obj 50 296 outlet; #X obj 50 129 pack f f; #X floatatom 50 95 5 0 0 0 - - -; #X floatatom 101 96 5 0 0 0 - - -; #X text 48 79 bin #; #X text 99 81 bin speed; #X msg 187 122 linespeed 0 -1 511 1; #X text 164 105 startbin startspeed endbin endspeed; #X text 164 222 minspeed maxspeed; #X msg 162 265 randphase 0 1; #X msg 188 163 linephase 0 0 511 1; #X msg 165 237 randspeed 0.95 1.05; #X text 47 53 phase is bounded by 0-1; #X text 47 39 bin numbers are bounded by 0-(FFT_size/2 - 1); #X msg 50 168 bin \$1 \$2; #X text 45 327 The cool thing here is that each FFT bin can be set to a different speed.; #X connect 1 0 14 0; #X connect 2 0 1 0; #X connect 3 0 1 1; #X connect 6 0 0 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X connect 11 0 0 0; #X connect 14 0 0 0; #X restore 210 176 pd separate-bin-control; #X text 334 157 then control it; #X connect 1 0 0 0; #X connect 2 0 0 0; #X connect 4 0 0 0; #X connect 5 0 0 0; #X connect 6 0 0 0; #X restore 135 92 pd messages; #X text 28 212 resent~ follows the model of residency~ but allows independent control over each bin. It is recommended that you familiarize yourself with residency~ before working with the more complicated resent~.; #X floatatom 135 150 5 0 0 0 - - -; #X text 117 167 record sync; #X text 155 71 <- first load a sound; #X text 228 93 <- then see what else you can do; #X connect 0 0 3 0; #X connect 2 0 1 0; #X connect 3 0 4 0; #X connect 3 0 4 1; #X connect 3 1 7 0; #X connect 5 0 3 1; fftease-2.5.2.git20121005/resent~.c0000644000076500007650000005213212067450034015056 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *resent_class; #endif #if PD static t_class *resent_class; #endif #define OBJECT_NAME "resent~" typedef struct _resent { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float *frame_incr; float *store_incr; float *frame_phase; float frameloc; float **loveboat; float current_frame; int framecount; // float frame_increment ; float *composite_frame ; float fpos; float last_fpos; float tadv; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // faster fft float mult; float *trigland; int *bitshuffle; int read_me; int frames_read; // int MAXFRAMES; short mute; void *m_clock; void *m_bang; short playthrough; int hopsize; int overlap; int winfac; short lock; float duration; short verbose; float sync; } t_resent; void *resent_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *resent_perform(t_int *w); void resent_dsp(t_resent *x, t_signal **sp, short *count); void resent_assist(t_resent *x, void *b, long m, long a, char *s); void resent_acquire_sample (t_resent *x) ; void resent_mute(t_resent *x, t_floatarg tog); void resent_bin(t_resent *x, t_floatarg fbin, t_floatarg speed); void resent_setphase(t_resent *x, t_floatarg phase); void resent_addphase(t_resent *x, t_floatarg phase); void resent_setspeed( t_resent *x, t_floatarg speed ); void resent_addspeed( t_resent *x, t_floatarg speed ); void resent_size( t_resent *x, t_floatarg size_ms ); void resent_free( t_resent *x ); void resent_store_incr( t_resent *x ); void resent_setspeed_and_phase( t_resent *x, t_floatarg speed, t_floatarg phase ); void resent_tick(t_resent *x); void resent_fftinfo(t_resent *x); void resent_init(t_resent *x, short flag); void resent_linephase(t_resent *x, t_symbol *msg, short argc, t_atom *argv); void resent_linespeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv); void resent_randphase(t_resent *x, t_symbol *msg, short argc, t_atom *argv); void resent_randspeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv); void resent_playthrough(t_resent *x, t_floatarg state); float resent_randf(float min, float max); void resent_winfac(t_resent *x, t_floatarg factor); void resent_verbose(t_resent *x, t_floatarg t); void resent_fftinfo(t_resent *x); void resent_overlap(t_resent *x, t_floatarg f); void resent_winfac(t_resent *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **)&resent_class, (method)resent_new, (method)resent_free, (short)sizeof(t_resent), 0L,A_GIMME,0); addmess((method)resent_dsp, "dsp", A_CANT, 0); addmess((method)resent_assist,"assist",A_CANT,0); addbang((method)resent_acquire_sample); addmess((method)resent_mute, "mute", A_FLOAT, 0); addmess((method)resent_linespeed, "linespeed", A_GIMME, 0); addmess((method)resent_linephase, "linephase", A_GIMME, 0); addmess((method)resent_randspeed, "randspeed", A_GIMME, 0); addmess((method)resent_randphase, "randphase", A_GIMME, 0); addmess((method)resent_bin, "bin", A_DEFFLOAT, A_DEFFLOAT, 0); addmess((method)resent_setphase, "setphase", A_DEFFLOAT, 0); addmess((method)resent_addphase, "addphase", A_DEFFLOAT, 0); addmess((method)resent_setspeed, "setspeed", A_DEFFLOAT, 0); addmess((method)resent_addspeed, "addspeed", A_DEFFLOAT, 0); addmess((method)resent_playthrough, "playthrough", A_DEFFLOAT, 0); addmess((method)resent_store_incr, "store_incr",0); addmess((method)resent_fftinfo, "fftinfo",0); addmess((method)resent_overlap, "overlap",A_FLOAT,0); addmess((method)resent_winfac, "winfac",A_FLOAT,0); addmess((method)resent_setspeed_and_phase, "setspeed_and_phase", A_DEFFLOAT, A_DEFFLOAT, 0); addmess((method)resent_size, "size", A_FLOAT,0); // addmess((method)resent_verbose, "verbose", A_FLOAT,0); addmess((method)resent_overlap,"overlap",A_DEFFLOAT,0); addmess((method)resent_winfac,"winfac",A_DEFFLOAT,0); addmess((method)resent_fftinfo,"fftinfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void resent_tilde_setup(void) { resent_class = class_new(gensym("resent~"), (t_newmethod)resent_new, (t_method)resent_free ,sizeof(t_resent), 0,A_GIMME,0); CLASS_MAINSIGNALIN(resent_class, t_resent, x_f); class_addmethod(resent_class,(t_method)resent_dsp,gensym("dsp"),0); class_addmethod(resent_class,(t_method)resent_mute,gensym("mute"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_linespeed,gensym("linespeed"),A_GIMME,0); class_addmethod(resent_class,(t_method)resent_linephase,gensym("linephase"),A_GIMME,0); class_addmethod(resent_class,(t_method)resent_randspeed,gensym("randspeed"),A_GIMME,0); class_addmethod(resent_class,(t_method)resent_randphase,gensym("randphase"),A_GIMME,0); class_addmethod(resent_class,(t_method)resent_bin,gensym("bin"),A_DEFFLOAT, A_DEFFLOAT,0); // Pd may still have parser bug for similar starting strings class_addmethod(resent_class,(t_method)resent_setspeed_and_phase,gensym("ssap"),A_DEFFLOAT, A_DEFFLOAT,0); class_addmethod(resent_class,(t_method)resent_setphase,gensym("setphase"),A_DEFFLOAT,0); class_addmethod(resent_class,(t_method)resent_addphase,gensym("addphase"),A_DEFFLOAT,0); class_addmethod(resent_class,(t_method)resent_setspeed,gensym("setspeed"),A_DEFFLOAT,0); class_addmethod(resent_class,(t_method)resent_addspeed,gensym("addspeed"),A_DEFFLOAT,0); class_addmethod(resent_class,(t_method)resent_fftinfo,gensym("fftinfo"),0); class_addmethod(resent_class,(t_method)resent_store_incr,gensym("store_incr"),0); class_addmethod(resent_class,(t_method)resent_playthrough,gensym("playthrough"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_size,gensym("size"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_verbose,gensym("verbose"),A_FLOAT,0); class_addmethod(resent_class,(t_method)resent_acquire_sample,gensym("acquire_sample"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void resent_verbose(t_resent *x, t_floatarg t) { x->verbose = (short)t; } void resent_overlap(t_resent *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; resent_init(x,1); } void resent_winfac(t_resent *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; resent_init(x,2); } void resent_fftinfo(t_resent *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void resent_size(t_resent *x, t_floatarg size) { x->duration = size/1000.0; resent_init(x,1); } void resent_store_incr(t_resent *x) { int i; float *store_incr = x->store_incr; float *frame_incr = x->frame_incr; for(i = 0; i < x->N2; i++){ store_incr[i] = frame_incr[i]; } } void resent_free(t_resent *x){ int i ; #if MSP dsp_free((t_pxobject *) x); #endif for(i = 0; i < x->framecount; i++){ freebytes(x->loveboat[i],0) ; } freebytes(x->frame_phase,0); freebytes(x->composite_frame,0); freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->frame_incr,0); freebytes(x->store_incr,0); } void resent_bin(t_resent *x, t_floatarg fbin, t_floatarg speed) { int bin_num = (int) fbin; if(bin_num >= 0 && bin_num < x->N2){ x->frame_incr[bin_num] = speed ; } else { post("resent~: bin %d is out of range", bin_num); } } void resent_setphase( t_resent *x, t_floatarg phase) { float scaled_phase ; int i; if( phase < 0. ) phase = 0. ; if( phase > 1. ) phase = 1.; scaled_phase = phase * (float) x->framecount ; for( i = 0; i < x->N2; i++ ){ x->frame_phase[i] = scaled_phase ; } } void resent_addphase( t_resent *x, t_floatarg phase ) { float scaled_phase ; float *frame_phase = x->frame_phase; int framecount = x->framecount; int i; if( phase < 0. ) phase = 0. ; if( phase > 1. ) phase = 1.; scaled_phase = phase * (float) framecount ; for( i = 0; i < x->N2; i++ ){ frame_phase[i] += scaled_phase ; while( frame_phase[i] < 0 ) frame_phase[i] += framecount; while( frame_phase[i] > framecount - 1 ) frame_phase[i] -= framecount ; } } void resent_setspeed( t_resent *x, t_floatarg speed ) { int i; for( i = 0; i < x->N2; i++ ){ x->frame_incr[i] = speed ; } // post("speed reset to %f",speed); } void resent_addspeed( t_resent *x, t_floatarg speed ) { int i; float *store_incr = x->store_incr; float *frame_incr = x->frame_incr; for( i = 0; i < x->N2; i++ ){ frame_incr[i] = store_incr[i] + speed ; } } void resent_setspeed_and_phase( t_resent *x, t_floatarg speed, t_floatarg phase ) { float scaled_phase ; int i; if( phase < 0. ) phase = 0. ; if( phase > 1. ) phase = 1.; scaled_phase = phase * (float) x->framecount ; for( i = 0; i < x->N2; i++ ){ x->frame_phase[i] = scaled_phase ; x->frame_incr[i] = speed ; } // post("ssap: speed reset to %f, phase reset to %f",speed,phase); } void resent_assist (t_resent *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal/bang) Input, Sample Trigger"); break; } } else if (msg==2) { switch( arg){ case 0: sprintf(dst,"(signal) Output "); break; case 1: sprintf(dst,"(signal) Recording Sync"); break; } } } void resent_tick(t_resent *x) { outlet_bang(x->m_bang); } void resent_init(t_resent *x,short initialized) { int i; int last_framecount = x->framecount; x->lock = 1; if(!x->D) x->D = 256; if(!x->R) x->R = 44100; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; if(!fftease_power_of_two(x->overlap)) x->overlap = 1; x->verbose = 0; // testing only x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->current_frame = x->framecount = 0; x->fpos = x->last_fpos = 0; x->tadv = (float)x->D/(float)x->R; x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(x->duration < .005){ x->duration = 1.0; } x->framecount = x->duration/x->tadv ; x->read_me = 0; if(!initialized){ x->frame_increment = 1.0 ; x->mute = 0; x->playthrough = 0; x->sync = 0; x->frames_read = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->composite_frame = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->frame_incr = (float *) getbytes( MAX_N2 * sizeof(float) ); x->store_incr = (float *) getbytes( MAX_N2 * sizeof(float) ); x->frame_phase = (float *) getbytes( MAX_N2 * sizeof(float) ); x->loveboat = (float **) getbytes(x->framecount * sizeof(float *)); for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes((x->N+2) * sizeof(float)); if(x->loveboat[i] == NULL){ error("Insufficient Memory!"); return; } memset((char *)x->loveboat[i],0,(x->N+2) * sizeof(float)); } } else if(initialized == 1){ for(i = 0; i < last_framecount; i++){ freebytes(x->loveboat[i],0) ; } freebytes(x->loveboat,0); x->loveboat = (float **) getbytes(x->framecount * sizeof(float *)); for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes((x->N+2) *sizeof(float)); if(x->loveboat[i] == NULL){ error("Insufficient Memory!"); return; } memset((char *)x->loveboat[i],0,(x->N+2) * sizeof(float)); } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1)* sizeof(float)); memset((char *)x->frame_incr,0,(x->N2)* sizeof(float)); memset((char *)x->store_incr,0,(x->N2) * sizeof(float)); memset((char *)x->frame_phase,0,(x->N2) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); x->hopsize = x->N / x->overlap; makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); x->lock = 0; } void *resent_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_resent *x = (t_resent *)newobject(resent_class); // x->m_bang = bangout((t_pxobject *)x); // x->m_clock = clock_new(x,(method)resent_tick); dsp_setup((t_pxobject *)x,1); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_resent *x = (t_resent *)pd_new(resent_class); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); // x->m_bang = outlet_new(&x->x_obj,gensym("bang")); // x->m_clock = clock_new(x,(void *)resent_tick); #endif srand(clock()); x->duration = atom_getfloatarg(0, argc, argv)/1000.0; x->overlap = atom_getfloatarg(1, argc, argv); x->winfac = atom_getfloatarg(2, argc, argv); x->D = sys_getblksize(); x->R = sys_getsr(); resent_init(x,0); return (x); } t_int *resent_perform(t_int *w) { int iphase, amp, freq, i, j; float fincr; float fpos; ////////////////////////////////////////////// t_resent *x = (t_resent *) (w[1]); float *frame_incr = x->frame_incr ; float *frame_phase = x->frame_phase ; float *composite_frame = x->composite_frame ; float in_sample; t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); t_float *sync_vec = (t_float *)(w[4]); t_int n = w[5]; /* dereference structure */ int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float fframe = x->current_frame ; float last_fpos = x->last_fpos ; int framecount = x->framecount; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; float sync = x->sync; sync = (float)x->frames_read / (float)x->framecount; if(x->mute || x->lock){ while(n--){ *out++ = 0.0; *sync_vec++ = sync; } return (w+6); } inCount += D; if(x->read_me){ for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } if(x->playthrough){ for (j = Nw - D; j < Nw; j++) { in_sample = input[j] = *in++; *out++ = in_sample * 0.5; // scale down *sync_vec++ = sync; } } else{ for (j = Nw - D; j < Nw; j++) { input[j] = *in++; *out++ = 0.0; *sync_vec++ = sync; } } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in ); if(x->frames_read >= x->framecount){ x->read_me = 0; } } else { for( i = 0 ; i < N2; i++ ){ amp = i<<1; freq = amp + 1 ; iphase = frame_phase[i] ; if( iphase < 0 ) iphase = 0; if( iphase > framecount - 1 ) iphase = framecount - 1; composite_frame[amp] = x->loveboat[iphase][amp]; composite_frame[freq] = x->loveboat[iphase][freq]; frame_phase[i] += frame_incr[i] ; while( frame_phase[i] > framecount - 1) frame_phase[i] -= framecount ; while( frame_phase[i] < 0. ) frame_phase[i] += framecount ; } unconvert(composite_frame, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount ); for (j = 0; j < D; j++){ *out++ = output[j] * mult; *sync_vec++ = sync; } for (j = 0; j < Nw - D; j++){ output[j] = output[j+D]; } for (j = Nw - D; j < Nw; j++){ output[j] = 0.; } } /* restore state variables */ x->inCount = inCount %Nw; x->current_frame = fframe; x->last_fpos = last_fpos; x->sync = sync; return (w+6); } void resent_acquire_sample(t_resent *x) { x->read_me = 1; x->frames_read = 0; return; } void resent_mute(t_resent *x, t_floatarg tog) { x->mute = tog; } void resent_playthrough(t_resent *x, t_floatarg state) { x->playthrough = state; } void resent_linephase(t_resent *x, t_symbol *msg, short argc, t_atom *argv) { int bin1, bin2; float phase1, phase2, bindiff; int i; float m1, m2; bin1 = (int) atom_getfloatarg(0, argc, argv); phase1 = atom_getfloatarg(1, argc, argv) * x->framecount; bin2 = (int) atom_getfloatarg(2, argc, argv); phase2 = atom_getfloatarg(3, argc, argv) * x->framecount; if( bin1 > x->N2 || bin2 > x->N2 ){ error("too high bin number"); return; } bindiff = bin2 - bin1; if( bindiff < 1 ){ error("make bin2 higher than bin 1, bye now"); return; } for( i = bin1; i < bin2; i++ ){ m2 = (float) i / bindiff; m1 = 1. - m2; x->frame_phase[i] = m1 * phase1 + m2 * phase2; } } void resent_randphase(t_resent *x, t_symbol *msg, short argc, t_atom *argv) { float minphase, maxphase; int i; int framecount = x->framecount; minphase = atom_getfloatarg(0, argc, argv); maxphase = atom_getfloatarg(1, argc, argv); // post("minphase %f maxphase %f",minphase, maxphase); if(minphase < 0.0) minphase = 0.0; if( maxphase > 1.0 ) maxphase = 1.0; for( i = 0; i < x->N2; i++ ){ x->frame_phase[i] = (int) (resent_randf( minphase, maxphase ) * (float) (framecount - 1) ) ; } } void resent_randspeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv) { float minspeed, maxspeed; int i; minspeed = atom_getfloatarg(0, argc, argv); maxspeed = atom_getfloatarg(1, argc, argv); for( i = 0; i < x->N2; i++ ){ x->frame_incr[i] = resent_randf(minspeed, maxspeed); } } void resent_linespeed(t_resent *x, t_symbol *msg, short argc, t_atom *argv) { int bin1, bin2; float speed1, speed2, bindiff; int i; float m1, m2; bin1 = (int) atom_getfloatarg(0, argc, argv); speed1 = atom_getfloatarg(1, argc, argv); bin2 = (int) atom_getfloatarg(2, argc, argv); speed2 = atom_getfloatarg(3, argc, argv); if( bin1 > x->N2 || bin2 > x->N2 ){ error("too high bin number"); return; } bindiff = bin2 - bin1; if( bindiff < 1 ){ error("make bin2 higher than bin 1, bye now"); return; } for( i = bin1; i < bin2; i++ ){ m2 = (float) i / bindiff; m1 = 1. - m2; x->frame_incr[i] = m1 * speed1 + m2 * speed2; } } void resent_dsp(t_resent *x, t_signal **sp, short *count) { if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; if(x->verbose) post("new vector size: %d, new sampling rate:%d",x->D,x->R); resent_init(x,1); } dsp_add(resent_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); } float resent_randf(float min,float max) { float rval; rval = (float) (rand() % RAND_MAX) / (float) RAND_MAX; return ( min + (max-min) * rval ); } fftease-2.5.2.git20121005/residency_buffer~.c0000644000076500007650000003340212067450034017073 0ustar hanshans#ifndef PD #include "MSPd.h" #include "fftease.h" /* #include "buffer.h" */ /* Not ported to Pd due to array/buffer difference */ // #define FLEN 1024 #if MSP void *resident_class; #endif #if PD static t_class *resident_class; #endif #define OBJECT_NAME "residency_buffer~" typedef struct _resident { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float current_frame; int framecount; // float frame_increment ; float fpos; float last_fpos; float tadv; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // faster fft float mult; float *trigland; int *bitshuffle; int read_me; int frames_read; int MAXFRAMES; short mute; short in2_connected; short in3_connected; int buffer_frame_count; // buffer t_symbol *l_sym; t_buffer *l_buf; short initialized; float *tmpframe; int hopsize; int overlap; int winfac; short playthrough; float sync; short buffer_is_hosed; } t_resident; void *resident_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *resident_perform(t_int *w); void resident_dsp(t_resident *x, t_signal **sp, short *count); void resident_assist(t_resident *x, void *b, long m, long a, char *s); void resident_bangname ( t_resident *x ) ; void resident_meminfo( t_resident *x ) ; void resident_float(t_resident *x, double f) ; void resident_mute(t_resident *x, long toggle); void resident_calcbuf(t_resident *x, double desired_duration); void resident_dsp_free( t_resident *x ); void resident_fftinfo(t_resident *x); void resident_winfac(t_resident *x, t_floatarg f); void resident_playthrough(t_resident *x, t_floatarg f); void resident_overlap(t_resident *x, t_floatarg f); resident_init(t_resident *x, short initialized); void main(void) { setup((t_messlist **)&resident_class, (method)resident_new, (method)resident_dsp_free, (short)sizeof(t_resident), 0L, A_GIMME,0); addmess((method)resident_dsp, "dsp", A_CANT, 0); addmess((method)resident_assist,"assist",A_CANT,0); addfloat((method) resident_float); addbang( (method) resident_bangname ); addmess ((method)resident_mute, "mute", A_LONG, 0); addmess ((method)resident_fftinfo, "meminfo", 0); addmess ((method)resident_calcbuf, "calcbuf", A_FLOAT, 0); addmess ((method)resident_winfac, "winfac", A_FLOAT, 0); addmess ((method)resident_overlap, "overlap", A_FLOAT, 0); addmess ((method)resident_playthrough, "playthrough", A_FLOAT, 0); addmess ((method)resident_fftinfo, "fftinfo", 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } void resident_meminfo( t_resident *x ) { post("%d frames in buffer", x->buffer_frame_count); post("frame_duration: %f, actual time in buffer: %f", x->tadv, (float)(x->buffer_frame_count) * x->tadv); post("actual time in buffer: %f", (float)(x->buffer_frame_count) * x->tadv); } void resident_fftinfo(t_resident *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void resident_dsp_free( t_resident *x ){ dsp_free( (t_pxobject *) x); freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->tmpframe,0); } void resident_calcbuf(t_resident *x, double desired_duration) { float ms_calc; float frames_needed; float seconds; float frames; float samples; seconds = desired_duration / 1000.0; frames = seconds / x->tadv; samples = frames * (float) (x->N + 2); ms_calc = (samples / x->R) * 1000.0; post("you need %.0f milliseconds in buffer to get %.0f frames", ms_calc, frames); } void resident_assist (t_resident *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal/bang) Input, Sampling Trigger"); break; case 1: sprintf(dst,"(signal/float) Frame Increment"); break; case 2: sprintf(dst,"(signal/float) Frame Position [0-1]"); break; } } else if (msg==2) { switch(arg) { case 1: sprintf(dst,"(signal) Output"); break; case 2: sprintf(dst,"(signal) Record Sync"); break; } } } void *resident_new(t_symbol *msg, short argc, t_atom *argv) { t_resident *x = (t_resident *)newobject(resident_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); x->D = sys_getblksize(); x->R = sys_getsr(); /* args: bufname, overlap, winfac */ x->l_sym = atom_getsymarg(0, argc, argv); x->overlap = atom_getintarg(1, argc, argv); x->winfac = atom_getintarg(2, argc, argv); // post("argc is %d", argc); it is the number of arguments, not including name of external if(argc < 1){ error("%s: you must provide the name of a valid buffer.",OBJECT_NAME); x->x_obj.z_disabled = 1; return 0; // kills object for good } else { x->x_obj.z_disabled = 0; } resident_init(x,0); return (x); } resident_init(t_resident *x, short initialized) { int i; if(!power_of_two(x->overlap)) x->overlap = 4; if(!power_of_two(x->winfac)) x->winfac = 1; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->hopsize = x->D; x->tadv = (float) x->D / (float) x->R; x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out =TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->mute = 0; x->sync = 0; x->initialized = 1; x->current_frame = x->framecount = 0; x->frame_increment = 1.0 ; x->fpos = x->last_fpos = 0; x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->tmpframe = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( (MAX_N * 2) * sizeof( int ) ); x->trigland = (float *) getbytes( (MAX_N * 2) * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); } t_int *resident_perform(t_int *w) { float sample, outsamp ; int index_offset; int i, j; ////////////////////////////////////////////// t_resident *x = (t_resident *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *increment = (t_float *)(w[3]); t_float *position = (t_float *)(w[4]); t_float *out = (t_float *)(w[5]); t_float *vec_sync = (t_float *)(w[6]); t_int n = w[7]; /* dereference structure */ int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float fframe = x->current_frame ; float fincr = x->frame_increment; float fpos = x->fpos; float last_fpos = x->last_fpos ; int framecount = x->framecount; float sync = x->sync; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; float *tmpframe = x->tmpframe; t_buffer *l_buf = x->l_buf; int frames_read = x->frames_read; int buffer_frame_count = x->buffer_frame_count; if (x->in2_connected) { fincr = *increment++; } if (x->in3_connected) { fpos = *position++; } inCount += D; if( (! x->initialized) || x->mute || x->x_obj.z_disabled ) { for ( j = 0; j < D; j++ ){ *out++ = 0.0; *vec_sync++ = sync; } return (w+8); // must be index of "n" + 1 } if( x->read_me ) { for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, tmpframe, N2, c_lastphase_in, c_fundamental, c_factor_in ); index_offset = (N+2) * frames_read; for( i = index_offset, j = 0; i < index_offset + N + 2; i++, j++ ){ l_buf->b_samples[i] = tmpframe[j]; } ++frames_read; // output empty buffers while reading sync = (float)frames_read/(float)(x->buffer_frame_count); if(x->playthrough){ for ( i=0, j = Nw - D; j < Nw; j++, i++ ) { out[i] = input[j]; vec_sync[j] = sync; } } else { for ( j = 0; j < D; j++ ){ out[j] = 0.0; vec_sync[j] = sync; } } if( frames_read >= x->buffer_frame_count){ x->read_me = 0; // post("resident_buffer: data acquisition completed"); } } else if (x->mute ) { // Process Muted for ( j = 0; j < D; j++ ){ out[j] = 0.0; vec_sync[j] = sync; } } else { if( fpos < 0 ) fpos = 0; if( fpos > 1 ) fpos = 1; if( fpos != last_fpos ){ fframe = fpos * (float) buffer_frame_count ; last_fpos = fpos; } fframe += fincr; while( fframe >= buffer_frame_count ) { fframe -= buffer_frame_count; } while( fframe < 0. ) { fframe += buffer_frame_count ; } index_offset = (N+2) * (int) fframe; for( i = index_offset, j = 0; i < index_offset + N + 2; i++, j++ ){ tmpframe[j] = l_buf->b_samples[i]; } // REPLACE loveboat with buffer unconvert( tmpframe, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount ); for ( j = 0; j < D; j++ ){ *out++ = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; vec_sync[0] = sync; } } /* restore state variables */ x->inCount = inCount % Nw; x->current_frame = fframe; x->frame_increment = fincr; x->fpos = fpos; x->last_fpos = last_fpos; x->frames_read = frames_read; x->sync = sync; return (w+8); } void resident_float(t_resident *x, double f) // Look at floats at inlets { // int inlet = ((t_pxobject*)x)->z_in; int inlet = x->x_obj.z_in; if (inlet == 1) { x->frame_increment = f; } else if (inlet == 2) { if (f < 0 ){ f = 0; } else if(f > 1) { f = 1.; } x->fpos = f; } } void resident_bangname ( t_resident *x ) { // int i, j; x->read_me = 1; x->frames_read = 0; // post("resident_buffer: beginning spectral data acquisition"); return; } void resident_mute(t_resident *x, long toggle) { x->mute = (short)toggle; } void resident_playthrough(t_resident *x, t_floatarg toggle) { x->playthrough = (short)toggle; } void resident_winfac(t_resident *x, t_floatarg f) { int i = (int)f; if(!power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; resident_init(x,2); } void resident_overlap(t_resident *x, t_floatarg f) { int i = (int) f; if(!power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; resident_init(x,1); } void resident_dsp(t_resident *x, t_signal **sp, short *count) { long i; int buffer_samples; t_buffer *b; x->in2_connected = count[1]; x->in3_connected = count[2]; if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; resident_init(x,1); } /* post("value of disabled is: %d",x->x_obj.z_disabled); post("value of initialized is: %d",x->initialized); */ /* if(x->l_sym->s_name == ""){ post("this buffer was not even dignified with a name"); } */ /* if(!x->l_sym->s_thing){ error("residency_buffer~: not linked to a valid buffer"); } */ // else if(!x->initialized){ if ((b = (t_buffer *)(x->l_sym->s_thing)) && ob_sym(b) == gensym("buffer~")) { x->l_buf = b; x->initialized = 1; if( x->l_buf->b_nchans != 1 ){ error("resident_buffer~: buffer \"%s\" must have 1 channel, not %d", x->l_sym->s_name, x->l_buf->b_nchans); x->x_obj.z_disabled = 1; } } else { error("%s: buffer \"%s\" not found",OBJECT_NAME, x->l_sym->s_name); x->x_obj.z_disabled = 1; } if( ! x->x_obj.z_disabled ){ x->buffer_frame_count = (float) (x->l_buf->b_frames) / (float)(x->N + 2 ); } // } dsp_add(resident_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } #endif /* PD */ fftease-2.5.2.git20121005/residency~-help.pd0000644000076500007650000000713012067450034016650 0ustar hanshans#N canvas 230 215 591 546 10; #N canvas 0 22 490 340 residency-block 0; #X obj 28 42 inlet~; #X obj 92 44 inlet~; #X obj 156 44 inlet~; #X obj 229 46 inlet; #X obj 28 140 outlet~; #X obj 28 99 residency~ 5000 4 1; #X obj 28 169 block~ 256; #X text 39 120 args: buffer size \, overlap \, window factor; #X text 103 171 FFT size is block~ size times overlap; #X obj 232 235 snapshot~; #X obj 393 187 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X obj 232 264 outlet; #X msg 393 142 loadbang; #X msg 393 165 1; #X obj 394 205 metro 100; #X connect 0 0 5 0; #X connect 1 0 5 1; #X connect 2 0 5 2; #X connect 3 0 5 0; #X connect 5 0 4 0; #X connect 5 1 9 0; #X connect 9 0 11 0; #X connect 10 0 14 0; #X connect 12 0 13 0; #X connect 13 0 10 0; #X connect 14 0 9 0; #X restore 124 220 pd residency-block; #N canvas 449 46 676 438 messages 0; #X obj 119 302 outlet; #X floatatom 289 121 5 0 0 2 resize_memory size -; #X msg 289 151 size \$1; #X obj 119 70 bng 15 250 50 0 empty trigger trigger_sampling 0 -6 0 8 -262144 -1 -1; #X obj 149 122 s playsound; #X obj 119 98 t b b; #X msg 119 149 acquire_sample; #X text 36 10 Load a valid soundfile in sound-source \, then hit the sampling trigger below. The resulting recording is stored as a series of FFT frames inside residency~ available for arbitrary time-access. ; #X text 254 134 first turn off DACs to be safe; #X obj 274 264 fftease-system; #N canvas 0 22 642 503 init 0; #X msg 241 126 verbose 1; #X msg 140 126 playthrough 1; #X obj 140 99 loadbang; #X obj 140 36 loadbang; #X msg 140 57 1; #X obj 140 79 s speed-slider; #X obj 130 194 outlet; #X connect 0 0 6 0; #X connect 1 0 6 0; #X connect 2 0 1 0; #X connect 2 0 0 0; #X connect 3 0 4 0; #X connect 4 0 5 0; #X restore 233 231 pd init; #X connect 1 0 2 0; #X connect 2 0 0 0; #X connect 3 0 5 0; #X connect 5 0 6 0; #X connect 5 1 4 0; #X connect 6 0 0 0; #X connect 9 0 0 0; #X connect 10 0 0 0; #X restore 245 185 pd messages; #X floatatom 164 196 5 0 0 0 - speed -; #N canvas 0 22 514 364 sound-source 0; #X obj 227 222 r playsound; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array residency-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 residency-sound1; #X obj 227 268 tabplay~ residency-sound1; #X text 63 132 open the sound; #X connect 0 0 6 0; #X connect 2 0 11 0; #X connect 4 0 2 0; #X connect 6 0 12 0; #X connect 7 0 6 0; #X connect 8 0 7 1; #X connect 11 0 1 0; #X connect 12 0 5 0; #X connect 12 1 7 0; #X restore 124 125 pd sound-source; #X obj 124 263 dac~; #X text 161 181 speed; #X msg 284 257 \; pd dsp \$1; #X obj 284 231 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X floatatom 204 168 5 0 1 2 position position -; #X obj 28 47 vsl 15 128 -2 2 0 0 speed speed-slider speed 0 -8 0 8 -253906 -1 -1 6325 1; #X obj 60 47 vsl 15 128 0 1 0 0 position empty position 0 -8 0 8 -4094 -1 -1 8000 1; #X text 329 185 <- ask me what I can do; #X floatatom 245 291 5 0 0 0 - - -; #X text 245 307 recording sync; #X text 112 352 residency~ is a spectral sampler. The first argument specifies how many milliseconds of sampling memory to use. Start conservatively. If you request more memory than is available \, you may experience difficulty.; #X connect 0 0 4 0; #X connect 0 0 4 1; #X connect 0 1 12 0; #X connect 1 0 0 3; #X connect 2 0 0 1; #X connect 3 0 0 0; #X connect 7 0 6 0; #X connect 8 0 0 2; fftease-2.5.2.git20121005/residency~.c0000644000076500007650000003543312067450034015550 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *residency_class; #endif #if PD static t_class *residency_class; #endif #define OBJECT_NAME "residency~" typedef struct _residency { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; float **loveboat; float current_frame; int framecount; // float frame_increment ; float fpos; float last_fpos; float tadv; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // faster fft float mult; float *trigland; int *bitshuffle; int read_me; int frames_read; // int MAXFRAMES; short mute; short virgin; short playthrough; short in2_connected; short in3_connected; int overlap; int winfac; int hopsize; // int windowsize; float duration; short lock; short verbose; short override; float *input_vec; float sync; } t_residency; void *residency_new(t_symbol *s, int argc, t_atom *argv); t_int *residency_perform(t_int *w); void residency_dsp(t_residency *x, t_signal **sp, short *count); void residency_assist(t_residency *x, void *b, long m, long a, char *s); void residency_bangname(t_residency *x) ; void residency_fftinfo(t_residency *x) ; void residency_playthrough( t_residency *x, t_floatarg tog) ; void residency_float(t_residency *x, double f) ; void residency_mute(t_residency *x, t_floatarg tog); void residency_free(t_residency *x); void residency_init(t_residency *x, short initialized); void residency_size(t_residency *x, t_floatarg newsize); void residency_winfac(t_residency *x, t_floatarg factor); void residency_overlap(t_residency *x, t_floatarg o); void residency_verbose(t_residency *x, t_floatarg t); void residency_acquire_sample(t_residency *x); void residency_meminfo( t_residency *x ); #if MSP void main(void) { setup((t_messlist **)&residency_class, (method)residency_new, (method)residency_free, (short)sizeof(t_residency), 0L, A_GIMME,0); addmess((method)residency_dsp, "dsp", A_CANT, 0); addmess((method)residency_assist,"assist",A_CANT,0); addfloat((method)residency_float); addbang((method)residency_bangname); addmess((method)residency_mute, "mute", A_FLOAT, 0); addmess((method)residency_fftinfo, "fftinfo", 0); addmess((method)residency_meminfo, "meminfo", 0); addmess((method)residency_playthrough, "playthrough", A_DEFFLOAT, 0); addmess((method)residency_size, "size", A_DEFFLOAT, 0); addmess((method)residency_overlap, "overlap", A_DEFFLOAT, 0); addmess((method)residency_winfac, "winfac", A_DEFFLOAT, 0); addmess((method)residency_verbose, "verbose", A_DEFFLOAT, 0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void residency_tilde_setup(void) { residency_class = class_new(gensym("residency~"), (t_newmethod)residency_new, (t_method)residency_free ,sizeof(t_residency), 0,A_GIMME,0); CLASS_MAINSIGNALIN(residency_class, t_residency, x_f); class_addmethod(residency_class,(t_method)residency_dsp,gensym("dsp"),0); class_addmethod(residency_class,(t_method)residency_mute,gensym("mute"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_fftinfo,gensym("fftinfo"),0); class_addmethod(residency_class,(t_method)residency_meminfo,gensym("meminfo"),0); class_addmethod(residency_class,(t_method)residency_playthrough,gensym("playthrough"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_size,gensym("size"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_verbose,gensym("verbose"),A_FLOAT,0); class_addmethod(residency_class,(t_method)residency_acquire_sample,gensym("acquire_sample"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void residency_meminfo( t_residency *x ) { post("%d frames in buffer", x->framecount); post("frame_duration: %f, actual time in buffer: %f", x->tadv, (float)(x->framecount) * x->tadv); } void residency_overlap(t_residency *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; residency_init(x,1); } void residency_winfac(t_residency *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; // post("called winfac"); residency_init(x,2); } void residency_fftinfo(t_residency *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void residency_verbose(t_residency *x, t_floatarg t) { x->verbose = t; } void residency_size(t_residency *x, t_floatarg newsize) { //protect with DACs off? if(newsize > 0.0){//could be horrendous size, but that's the user's problem x->duration = newsize/1000.0; residency_init(x,1); } } void residency_playthrough (t_residency *x, t_floatarg tog) { x->playthrough = tog; } void residency_free(t_residency *x){ int i ; #if MSP dsp_free((t_pxobject *)x); #endif for(i = 0; i < x->framecount; i++){ freebytes(x->loveboat[i],0) ; } freebytes(x->loveboat,0); freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); } void residency_init(t_residency *x, short initialized) { int i; int last_framecount = x->framecount; x->lock = 1; x->virgin = 1; if(!x->winfac) x->winfac = 1; if(!x->overlap) x->overlap = 4; if(!x->R) x->R = 44100; if(!x->D) x->D = 256; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->current_frame = 0; x->fpos = x->last_fpos = 0; x->tadv = (float)x->D/(float)x->R; x->c_fundamental = (float)x->R/((x->N2)<<1); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float)x->D / (float)x->R; if( x->duration <= 0 ){ x->duration = 1.0; } x->framecount = x->duration / x->tadv ; x->hopsize = x->N / x->overlap; x->read_me = 0; if(!initialized){ x->sync = 0; x->mute = 0; x->in2_connected = 0; x->in3_connected = 0; x->playthrough = 0; x->frame_increment = 1.0; x->verbose = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->input_vec = (float *) getbytes(8192 * sizeof(float)); x->loveboat = (float **) getbytes(x->framecount * sizeof(float *)); for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes(((x->N)+2) * sizeof(float)); if(x->loveboat[i] == NULL){ error("memory error"); return; } memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float)); } } else if(initialized == 1){ for(i = 0; i < last_framecount; i++){ freebytes(x->loveboat[i],0) ; } freebytes(x->loveboat,0); x->loveboat = (float **) getbytes(x->framecount * sizeof(float *)); for(i=0;iframecount;i++){ x->loveboat[i] = (float *) getbytes((x->N+2) * sizeof(float)); if(x->loveboat[i] == NULL){ error("memory error"); return; } memset((char *)x->loveboat[i],0,(x->N+2)*sizeof(float)); } } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); makewindows( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D); init_rdft( x->N, x->bitshuffle, x->trigland); x->lock = 0; } void *residency_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_residency *x = (t_residency *)newobject(residency_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_residency *x = (t_residency *)pd_new(residency_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif // x->x_obj.z_misc |= Z_NO_INPLACE; x->duration = atom_getfloatarg(0,argc,argv)/1000.0; x->overlap = atom_getfloatarg(1,argc,argv); x->winfac = atom_getfloatarg(2,argc,argv); x->D = sys_getblksize(); x->R = sys_getsr(); residency_init(x,0); return (x); } t_int *residency_perform(t_int *w) { int i, j; float sample; ////////////////////////////////////////////// t_residency *x = (t_residency *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *increment = (t_float *)(w[3]); t_float *position = (t_float *)(w[4]); t_float *out = (t_float *)(w[5]); t_float *vec_sync = (t_float *) (w[6]); t_int n = w[7]; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float *input_vec = x->input_vec; float fframe = x->current_frame ; float last_fpos = x->last_fpos ; int framecount = x->framecount; float fincr = x->frame_increment; float fpos = x->fpos; float mult = x->mult; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; float sync = x->sync; if(x->lock || x->mute){ while(n--){ *out++ = 0.0; *vec_sync++ = sync; } return (w+8); } #if MSP if (x->in2_connected) { fincr = *increment; } if (x->in3_connected) { fpos = *position; } #endif #if PD fincr = *increment; fpos = *position; #endif inCount += D; for(i = 0; i < D; i++){ input_vec[i] = in[i]; } if(x->read_me) { for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for (i = 0,j = Nw - D; j < Nw; j++, i++) { input[j] = input_vec[i]; } if(framecount > 0) sync = (float)x->frames_read/(float)framecount; if( x->playthrough ){ for ( i = 0, j = Nw - D; j < Nw; j++, i++ ) { out[i] = input_vec[i] * 0.5; vec_sync[i] = sync; } } else { for ( j = 0; j < D; j++ ){ out[j] = 0.0; vec_sync[j] = sync; } } fold(input, Wanal, Nw, buffer, N, inCount); rdft(N, 1, buffer, bitshuffle, trigland); if(x->frames_read >= framecount){ x->read_me = 0; if(x->verbose){ post("residency: data acquisition completed"); } } else { convert(buffer, x->loveboat[(x->frames_read)++], N2, c_lastphase_in, c_fundamental, c_factor_in); } x->virgin = 0; } else if(x->playthrough && x->virgin){ for(i=0;i 1) fpos = 1; if(fpos != last_fpos){ fframe = fpos * (float) framecount ; last_fpos = fpos; } fframe += fincr; while(fframe >= framecount) { fframe -= framecount; } while( fframe < 0. ) { fframe += framecount ; } unconvert(x->loveboat[(int) fframe ], buffer, N2, c_lastphase_out, c_fundamental, c_factor_out); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount ); for(i = 0; i < D; i++){ vec_sync[i] = sync; } for ( j = 0; j < D; j++ ){ out[j] = output[j] * mult; } for ( j = 0; j < Nw - D; j++ ){ output[j] = output[j+D]; } for ( j = Nw - D; j < Nw; j++ ){ output[j] = 0.; } } /* restore state variables */ x->inCount = inCount % Nw; x->current_frame = fframe; x->frame_increment = fincr; x->fpos = fpos; x->last_fpos = last_fpos; x->sync = sync; return (w+8); } #if MSP void residency_float(t_residency *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->frame_increment = f; } else if (inlet == 2) { if (f < 0 ){ f = 0; } else if(f > 1) { f = 1.; } x->fpos = f; } } #endif void residency_acquire_sample(t_residency *x) { x->read_me = 1; x->frames_read = 0; post("beginning spectral data acquisition"); return; } void residency_bangname (t_residency *x) { x->read_me = 1; x->frames_read = 0; if(x->verbose) post("beginning spectral data acquisition"); return; } void residency_mute(t_residency *x, t_floatarg tog) { x->mute = tog; } void residency_dsp(t_residency *x, t_signal **sp, short *count) { #if MSP x->in2_connected = count[1]; x->in3_connected = count[2]; #endif if(x->R != sp[0]->s_sr || x->D != sp[0]->s_n){ x->R = sp[0]->s_sr; x->D = sp[0]->s_n; if(x->verbose) post("new vsize: %d, new SR:%d",x->D,x->R); residency_init(x,1); } dsp_add(residency_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } void residency_assist(t_residency *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal/bang) Input, Sampling Trigger"); break; case 1: sprintf(dst,"(signal/float) Frame Increment");break; case 2:sprintf(dst,"(signal/float) Frame Position [0-1]");break; } } else if (msg==2) { switch(arg){ case 0: sprintf(dst,"(signal) Output"); break; case 1: sprintf(dst,"(signal) Recording Sync"); break; } } } fftease-2.5.2.git20121005/scrape~-help.pd0000644000076500007650000000477212067450034016151 0ustar hanshans#N canvas 153 350 531 534 10; #N canvas 0 22 462 312 scrape-block 0; #X obj 134 142 scrape~ 1000 4000 0.001 0.05 0.1 4 1; #X obj 126 237 block~ 256; #X obj 134 188 outlet~; #X obj 134 74 inlet~; #X obj 198 84 inlet; #X obj 239 84 inlet; #X obj 282 84 inlet; #X obj 324 85 inlet; #X obj 366 85 inlet; #X obj 421 94 inlet; #X connect 0 0 2 0; #X connect 3 0 0 0; #X connect 4 0 0 1; #X connect 5 0 0 2; #X connect 6 0 0 3; #X connect 7 0 0 4; #X connect 8 0 0 5; #X connect 9 0 0 0; #X restore 61 203 pd scrape-block; #N canvas 0 22 470 320 messages 0; #X obj 200 244 outlet; #X obj 200 212 fftease-system; #X connect 1 0 0 0; #X restore 161 182 pd messages; #N canvas 0 22 470 320 playsound 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array scrape-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 63 132 open the sound; #X msg 31 177 read -resize \$1 scrape-sound1; #X obj 227 268 tabplay~ scrape-sound1; #X connect 1 0 11 0; #X connect 3 0 1 0; #X connect 5 0 12 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 11 0 0 0; #X connect 12 0 4 0; #X connect 12 1 6 0; #X restore 61 22 pd playsound; #X floatatom 77 53 5 0 0 1 knee - -; #X floatatom 94 75 5 0 0 1 cutoff - -; #X floatatom 111 97 5 0 0 1 threshold1 - -; #X floatatom 127 115 5 0 0 1 threshold2 - -; #X floatatom 144 135 5 0 0 1 weak_bin_multiplier - -; #X obj 61 240 dac~; #X msg 223 235 \; pd dsp \$1; #X obj 223 215 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X msg 287 14 1000 4000 0.001 0.05 0.1; #X obj 287 37 unpack f f f f f; #X obj 287 -7 loadbang; #X text 54 284 scrape~ is like drown~ except that it only operates between the frequencies specified by knee and cutoff to the Nyquist. Between knee and cutoff is a transition range to gradually increase the noise reduction. This is good if you just want to scrape some noise off the upper frequency range without affecting lower parts of the spectrum (much).; #X connect 0 0 8 0; #X connect 0 0 8 1; #X connect 1 0 0 6; #X connect 2 0 0 0; #X connect 3 0 0 1; #X connect 4 0 0 2; #X connect 5 0 0 3; #X connect 6 0 0 4; #X connect 7 0 0 5; #X connect 10 0 9 0; #X connect 11 0 12 0; #X connect 12 0 3 0; #X connect 12 1 4 0; #X connect 12 2 5 0; #X connect 12 3 6 0; #X connect 12 4 7 0; #X connect 13 0 11 0; fftease-2.5.2.git20121005/scrape~.c0000644000076500007650000002750112067450034015035 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *scrape_class; #endif #if PD static t_class *scrape_class; #endif #define OBJECT_NAME "scrape~" typedef struct _scrape { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; float *Wanal; float *Wsyn; float *input; float *Hwin; float *buffer; float *channel; float *output; // float knee; float cutoff; float scrape_mult; float thresh1; float thresh2; float *threshfunc; short connected[8]; short mute; short bypass; // float mult; float *trigland; int *bitshuffle; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_scrape; void *scrape_new(t_symbol *msg, short argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *scrape_perform(t_int *w); void scrape_dsp(t_scrape *x, t_signal **sp, short *count); void scrape_assist(t_scrape *x, void *b, long m, long a, char *s); void scrape_float(t_scrape *x, double f) ; void update_thresh_function( t_scrape *x ); void scrape_frowned( float *S, float *C, float *threshfunc, float fmult, int N2 ); void scrape_mute(t_scrape *x, t_floatarg toggle); void scrape_bypass(t_scrape *x, t_floatarg toggle); void scrape_dsp_free( t_scrape *x ); void update_thresh_function( t_scrape *x ); void scrape_init(t_scrape *x, short initialized); void scrape_fftinfo(t_scrape *x); void scrape_overlap(t_scrape *x, t_floatarg f); void scrape_winfac(t_scrape *x, t_floatarg f); #if MSP void main(void) { setup((t_messlist **) &scrape_class, (method)scrape_new, (method)scrape_dsp_free, (short)sizeof(t_scrape), 0, A_GIMME, 0); addmess((method)scrape_dsp, "dsp", A_CANT, 0); addmess((method)scrape_assist,"assist",A_CANT,0); addmess ((method)scrape_mute, "mute", A_FLOAT, 0); addmess ((method)scrape_bypass, "bypass", A_FLOAT, 0); addmess((method)scrape_overlap,"overlap",A_DEFFLOAT,0); addmess((method)scrape_winfac,"winfac",A_DEFFLOAT,0); addmess((method)scrape_fftinfo,"fftinfo",0); addfloat((method) scrape_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void scrape_tilde_setup(void) { scrape_class = class_new(gensym("scrape~"), (t_newmethod)scrape_new, (t_method)scrape_dsp_free ,sizeof(t_scrape), 0,A_GIMME,0); CLASS_MAINSIGNALIN(scrape_class, t_scrape, x_f); class_addmethod(scrape_class, (t_method)scrape_dsp, gensym("dsp"), 0); class_addmethod(scrape_class, (t_method)scrape_assist, gensym("assist"), 0); class_addmethod(scrape_class, (t_method)scrape_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(scrape_class, (t_method)scrape_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(scrape_class, (t_method)scrape_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(scrape_class,(t_method)scrape_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(scrape_class,(t_method)scrape_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void scrape_dsp_free( t_scrape *x ) { #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->threshfunc,0); } void scrape_assist (t_scrape *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input ");break; case 1: sprintf(dst,"(float/signal) Knee Frequency"); break; case 2: sprintf(dst,"(float/signal) Cutoff Frequency"); break; case 3: sprintf(dst,"(float/signal) Knee Threshold"); break; case 4: sprintf(dst,"(float/signal) Cutoff Threshold"); break; case 5: sprintf(dst,"(float/signal) Multiplier For Weak Bins"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void *scrape_new(t_symbol *msg, short argc, t_atom *argv) { #if MSP t_scrape *x = (t_scrape *)newobject(scrape_class); dsp_setup((t_pxobject *)x,6); outlet_new((t_pxobject *)x, "signal"); #endif #if PD int i; t_scrape *x = (t_scrape *)pd_new(scrape_class); for(i=0;i<5;i++) inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->knee = atom_getfloatarg(0, argc, argv); x->cutoff = atom_getfloatarg(1, argc, argv); x->thresh1 = atom_getfloatarg(2, argc, argv); x->thresh2 = atom_getfloatarg(3, argc, argv); x->scrape_mult = atom_getfloatarg(4, argc, argv); x->overlap = atom_getfloatarg(5, argc, argv); x->winfac = atom_getfloatarg(6, argc, argv); if(x->knee <= 0) x->knee = 1000.0; if(x->cutoff <= 0) x->cutoff = 4000.0; if(x->thresh1 <= 0) x->thresh1 = .0001 ; if(x->thresh2 <= 0) x->thresh2 = .09 ; if( x->scrape_mult < 0 || x->scrape_mult > 10 ){ x->scrape_mult = 0.1; } if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->vs = sys_getblksize(); x->R = sys_getsr(); scrape_init(x,0); return (x); } void scrape_init(t_scrape *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->threshfunc = (float *) getbytes(MAX_N2 * sizeof(float)); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); init_rdft( x->N, x->bitshuffle, x->trigland); if(initialized != 2) update_thresh_function(x); } void scrape_overlap(t_scrape *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; scrape_init(x,1); } void scrape_winfac(t_scrape *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; scrape_init(x,2); } void scrape_fftinfo(t_scrape *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } #if MSP void scrape_float(t_scrape *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { if( f> 50 && f < 18000) { x->knee = f ; update_thresh_function( x ); } } else if (inlet == 2) { if( (f > x->knee) && (f < 20000) ) { x->cutoff = f ; update_thresh_function( x ); } } else if (inlet == 3) { x->thresh1 = f; update_thresh_function( x ); } else if (inlet == 4) { x->thresh2 = f; update_thresh_function( x ); } else if (inlet == 5) { if( f > 0 ) { x->scrape_mult = f; } } } #endif void update_thresh_function( t_scrape *x ) { float funda, curfreq, m1, m2; int i; funda = (float) x->R / ((float)x->N * 2.0 ); curfreq = funda ; for( i = 0; i < x->N2; i++ ) { if( curfreq < x->knee ){ x->threshfunc[i] = 0.0 ; } else if( curfreq >= x->knee && curfreq < x->cutoff ) { m2 = (x->knee - curfreq) / (x->cutoff - x->knee) ; m1 = 1.0 - m2 ; x->threshfunc[i] = m1 * x->thresh1 + m2 * x->thresh2 ; } else { x->threshfunc[i] = x->thresh2; } curfreq += funda ; } } void scrape_mute(t_scrape *x, t_floatarg toggle) { x->mute = (short)toggle; } void scrape_bypass(t_scrape *x, t_floatarg toggle) { x->bypass = (short)toggle; } t_int *scrape_perform(t_int *w) { float sample, outsamp ; int i,j; float tmp ; short update = 0; t_scrape *x = (t_scrape *) (w[1]); t_float *in = (t_float *)(w[2]); t_float *knee_freq = (t_float *)(w[3]); t_float *cut_freq = (t_float *)(w[4]); t_float *thresh1 = (t_float *)(w[5]); t_float *thresh2 = (t_float *)(w[6]); t_float *scrape_mult = (t_float *)(w[7]); t_float *out = (t_float *)(w[8]); t_int n = w[9]; int inCount = x->inCount; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *channel = x->channel; float mult = x->mult ; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland ; float *threshfunc = x->threshfunc ; short *connected = x->connected; if( x->mute ){ while( n-- ){ *out++ = 0.0; } return (w+10); // always what dsp_add says + 1 } if( x->bypass ){ while( n-- ){ *out++ = *in++ * 0.5; // gain compensation } return (w+10); // always what dsp_add says + 1 } if( connected[1] ){ tmp = *knee_freq++; if( tmp > 50 && tmp < 20000 ){ x->knee = tmp; update = 1; } } if( connected[2] ){ tmp = *cut_freq++; if( tmp > x->knee && tmp < 20000 ){ x->cutoff = *cut_freq++; update = 1; } } if( connected[3] ){ x->thresh1 = *thresh1++ ; update = 1; } if( connected[4] ){ x->thresh2 = *thresh2++ ; update = 1; } if( connected[5] ){ x->scrape_mult = *scrape_mult++ ; } if( update ){ update_thresh_function( x ); } x->inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input[j] = input[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, inCount ); rdft( N, 1, buffer, bitshuffle, trigland ); scrape_frowned( buffer, channel, threshfunc, x->scrape_mult, N2 ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; return (w+10); // always what dsp_add says + 1 } void scrape_frowned( float *S, float *C, float *threshfunc, float fmult, int N2 ) { int real, imag, amp, phase; float a, b; int i; float maxamp = 1.; for( i = 0; i <= N2; i++ ){ amp = i<<1; if( maxamp < C[amp] ){ maxamp = C[amp]; } } for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; a = ( i == N2 ? S[1] : S[real] ); b = ( i == 0 || i == N2 ? 0. : S[imag] ); C[amp] = hypot( a, b ); if ( (C[amp]) < threshfunc[i] * maxamp ){ C[amp] *= fmult; } C[phase] = -atan2( b, a ); } for ( i = 0; i <= N2; i++ ) { imag = phase = ( real = amp = i<<1 ) + 1; S[real] = *(C+amp) * cos( *(C+phase) ); if ( i != N2 ) S[imag] = -*(C+amp) * sin( *(C+phase) ); } } void scrape_dsp(t_scrape *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 6; i++ ){ x->connected[i] = count[i]; } #endif #if PD for( i = 0; i < 6; i++ ){ x->connected[i] = 1; } #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; scrape_init(x,1); } dsp_add(scrape_perform, 9, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[5]->s_vec, sp[6]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/shapee~-help.pd0000644000076500007650000000604112067450034016130 0ustar hanshans#N canvas 263 477 494 344 10; #N canvas 657 88 510 360 messages 0; #X obj 160 251 outlet; #X obj 160 215 fftease-system; #X obj 308 200 loadbang; #X msg 308 235 16; #X obj 308 264 outlet; #X connect 1 0 0 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X restore 248 126 pd messages; #X obj 148 221 dac~; #X msg 210 242 \; pd dsp \$1; #X obj 210 212 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X floatatom 212 175 5 0 1 0 - - -; #N canvas 638 45 502 352 shapee-block 0; #X obj 150 160 outlet~; #X obj 150 66 inlet~; #X obj 229 70 inlet~; #X obj 411 78 inlet; #X obj 150 115 shapee~ 4 1; #X floatatom 279 149 5 0 0 0 - - -; #X obj 329 72 inlet; #X obj 154 253 block~ 512; #X connect 1 0 4 0; #X connect 2 0 4 1; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 4 2; #X connect 6 0 4 2; #X restore 148 153 pd shapee-block; #X floatatom 214 98 5 0 0 0 - - -; #X text 258 99 shaping width; #N canvas 501 137 751 450 pitch-source 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array shapee-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 shapee-sound1; #X obj 227 268 tabplay~ shapee-sound1; #X text 63 132 open the pitched sound; #X connect 1 0 10 0; #X connect 3 0 1 0; #X connect 5 0 11 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 10 0 0 0; #X connect 11 0 4 0; #X connect 11 1 6 0; #X restore 148 25 pd pitch-source; #N canvas 0 22 495 403 formant-source 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array shapee-sound2 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ shapee-sound2; #X msg 31 177 read -resize \$1 shapee-sound2; #X text 36 337 try a vocal sound or other sound with strong formant structure; #X text 63 132 open the formant sound; #X connect 1 0 11 0; #X connect 3 0 1 0; #X connect 5 0 10 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 10 0 4 0; #X connect 10 1 6 0; #X connect 11 0 0 0; #X restore 181 49 pd formant-source; #X obj 320 160 hsl 128 15 0 2 0 0 empty empty empty -2 -6 0 8 -195520 -1 -1 5200 1; #X text 321 146 gain; #X obj 148 188 *~ 0.1; #X text 40 287 shapee~ shapes the frequency evolution of one signal with that of another. The shape width controls the amount of the frequency shaping effect. Try to avoid sounds containing silence \, which can cause strong clicks.; #X connect 0 0 5 3; #X connect 0 1 6 0; #X connect 3 0 2 0; #X connect 4 0 12 1; #X connect 5 0 12 0; #X connect 6 0 5 2; #X connect 8 0 5 0; #X connect 9 0 5 1; #X connect 10 0 4 0; #X connect 12 0 1 0; #X connect 12 0 1 1; fftease-2.5.2.git20121005/shapee~.c0000644000076500007650000002724712067450034015034 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *shapee_class; #endif #if PD static t_class *shapee_class; #endif #define OBJECT_NAME "shapee~" typedef struct _shapee { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int widthConnected; int *bitshuffle; float shapeWidth; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; int overlap;//overlap factor int winfac;// window factor int vs;//last measurement of vector size short mute; } t_shapee; /* msp function prototypes */ void *shapee_new(t_symbol *s, int argc, t_atom *argv); t_int *shapee_perform(t_int *w); void shapee_dsp(t_shapee *x, t_signal **sp, short *count); void shapee_float(t_shapee *x, double myFloat); void shapee_assist(t_shapee *x, void *b, long m, long a, char *s); void shapee_init(t_shapee *x, short initialized); void shapee_mute(t_shapee *x, t_floatarg state); void shapee_free(t_shapee *x); void shapee_overlap(t_shapee *x, t_floatarg o); void shapee_winfac(t_shapee *x, t_floatarg wf); void shapee_fftinfo(t_shapee *x); /* first calling */ /* float input handling routine for shape width */ #if MSP void shapee_float( t_shapee *x, double myFloat ) { if ( x->x_obj.z_in == 2 ) { if ( myFloat >= 1. && myFloat <= (double) x->N ) x->shapeWidth = (float)myFloat; } } void main(void) { setup( (t_messlist **) &shapee_class, (method) shapee_new, (method) shapee_free, (short) sizeof(t_shapee), 0, A_GIMME, 0); addmess((method)shapee_dsp, "dsp", A_CANT, 0); addmess((method)shapee_assist,"assist",A_CANT,0); addfloat((method)shapee_float); addmess((method)shapee_mute,"mute",A_FLOAT,0); addmess((method)shapee_overlap,"overlap",A_FLOAT,0); addmess((method)shapee_winfac,"winfac",A_FLOAT,0); addmess((method)shapee_fftinfo,"fftinfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void shapee_tilde_setup(void) { shapee_class = class_new(gensym("shapee~"), (t_newmethod)shapee_new, (t_method)shapee_free ,sizeof(t_shapee), 0,A_GIMME,0); CLASS_MAINSIGNALIN(shapee_class, t_shapee, x_f); class_addmethod(shapee_class, (t_method)shapee_dsp, gensym("dsp"), 0); class_addmethod(shapee_class, (t_method)shapee_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(shapee_class, (t_method)shapee_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(shapee_class, (t_method)shapee_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(shapee_class, (t_method)shapee_fftinfo, gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif /* diagnostic messages for Max */ void shapee_assist (t_shapee *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Frequency Reference");break; case 1: sprintf(dst,"(signal) Amplitude Reference");break; case 2: sprintf(dst,"(signal/float) Shape Width"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void *shapee_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_shapee *x = (t_shapee *) newobject(shapee_class); dsp_setup((t_pxobject *)x, 3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_shapee *x = (t_shapee *)pd_new(shapee_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* INITIALIZATIONS */ x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!x->winfac) x->winfac = 1; if(!x->overlap) x->overlap = 4; x->vs = sys_getblksize(); x->R = sys_getsr(); shapee_init(x,0); return (x); } void shapee_init(t_shapee *x, short initialized) { int i; x->D = x->vs; x->N = x->vs * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) ); x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);// wants an ODD window } void shapee_fftinfo(t_shapee *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void shapee_mute(t_shapee *x, t_floatarg state) { x->mute = (short)state; } void shapee_overlap(t_shapee *x, t_floatarg o) { int test = (int) o; if(!fftease_power_of_two(test)){ post("%d is not a power of two",test); return; } x->overlap = test; shapee_init(x,1); } void shapee_winfac(t_shapee *x, t_floatarg wf) { int test = (int) wf; if(!fftease_power_of_two(test)){ post("%d is not a power of two",test); return; } x->winfac = test; shapee_init(x,1); } t_int *shapee_perform(t_int *w) { int n, i,j, inCount, R, N, N2, D, Nw, invert = 1, shapeWidth, remainingWidth, even, odd, *bitshuffle; float maxamp, threshMult = 1., mult, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; t_float *inOne, *inTwo, *inShape, *out; /* get our inlets and outlets */ t_shapee *x = (t_shapee *) (w[1]); inOne = (t_float *) (w[2]); inTwo = (t_float *) (w[3]); inShape = (t_float *) (w[4]); out = (t_float *)(w[5]); n = (t_int) (w[6]); /* get our shapeWidth -- from either a signal our float input */ #if MSP shapeWidth = x->widthConnected ? (int) *inShape : (int) x->shapeWidth; #endif #if PD shapeWidth = (int) *inShape; #endif /* dereference structure */ if(x->mute){ while(n--) *out++ = 0.0; return w+7; } inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; if(shapeWidth < 1 || shapeWidth > N2) shapeWidth = 1; inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); /* replace signal one's phases with those of signal two */ *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); } /* constrain our shapeWidth value */ if ( shapeWidth > N2 ) shapeWidth = N2; if ( shapeWidth < 1 ) shapeWidth = 1; /* lets just shape the entire signal by the shape width */ for ( i=0; i < N; i += shapeWidth << 1 ) { float amplSum = 0., freqSum = 0., factor; for ( j = 0; j < shapeWidth << 1; j += 2 ) { amplSum += *(channelTwo+i+j); freqSum += *(channelOne+i+j); } if(freqSum <= 0.001){ freqSum = 1.0; } if (amplSum < 0.000000001) factor = 0.000000001; else factor = amplSum / freqSum; for ( j = 0; j < shapeWidth * 2; j += 2 ) *(channelOne+i+j) *= factor; } /* copy remaining magnitudes */ if ( (remainingWidth = N2 % shapeWidth) ) { int bindex = (N2 - remainingWidth) << 1; float amplSum = 0., freqSum = 0., factor; for ( j = 0; j < remainingWidth * 2; j += 2 ) { amplSum += *(channelTwo+bindex+j); freqSum += *(channelOne+bindex+j); } if(freqSum <= 0.00001){ freqSum = 1.0; } if (amplSum < 0.000000001) factor = 0.000000001; else factor = amplSum / freqSum; for ( j = 0; j < remainingWidth * 2; j += 2 ) *(channelOne+bindex+j) *= factor; } /* convert from polar to cartesian */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = (*(channelOne+even)) * -sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void shapee_free( t_shapee *x ) { #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->inputTwo,0); freebytes(x->bufferOne,0); freebytes(x->bufferTwo,0); freebytes(x->channelOne,0); freebytes(x->channelTwo,0); freebytes(x->output,0); } void shapee_dsp(t_shapee *x, t_signal **sp, short *count) { #if MSP x->widthConnected = count[2]; #endif if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; shapee_init(x,1); } dsp_add(shapee_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/swinger~-help.pd0000644000076500007650000000516612067450034016350 0ustar hanshans#N canvas 263 477 470 320 10; #N canvas 0 22 478 328 swinger-block 0; #X obj 150 160 outlet~; #X obj 150 66 inlet~; #X obj 229 70 inlet~; #X obj 293 82 inlet; #X obj 179 224 block~ 512; #X obj 150 115 swinger~ 4 1; #X connect 1 0 5 0; #X connect 2 0 5 1; #X connect 3 0 5 0; #X connect 5 0 0 0; #X restore 148 121 pd swinger-block; #N canvas 0 22 478 328 messages 0; #X obj 160 251 outlet; #X obj 160 227 fftease-system; #X connect 1 0 0 0; #X restore 255 94 pd messages; #X obj 148 189 dac~; #X obj 148 156 *~ 1; #X msg 210 210 \; pd dsp \$1; #X obj 210 180 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X floatatom 212 143 5 0 0 0 - - -; #X text 41 255 swinger~ replaces the phases of one signal (left) with those from another (right). The result often sounds like victory. A swinging trick: Don't connect any signal to the right inlet and listen to the result.; #N canvas 538 45 558 447 sound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array swinger-sound1 1.5435e+06 float 2; #X coords 0 1 1.5435e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 133 244 then play it; #X text 304 190 loop if you like; #X msg 31 177 read -resize \$1 swinger-sound1; #X obj 227 268 tabplay~ swinger-sound1; #X text 64 132 open the sound; #X connect 1 0 10 0; #X connect 3 0 1 0; #X connect 5 0 11 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 10 0 0 0; #X connect 11 0 4 0; #X connect 11 1 6 0; #X restore 148 51 pd sound1; #N canvas 0 22 758 461 sound2 0; #X obj 161 265 soundfiler; #X obj 161 231 openpanel; #N canvas 0 22 450 300 graph1 0; #X array swinger-sound2 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 367 84 graph; #X msg 161 202 bang; #X obj 357 355 outlet~; #X msg 357 315 bang; #X obj 478 299 spigot; #X obj 515 276 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 263 315 then play it; #X text 434 261 loop if you like; #X text 193 203 open the sound; #X obj 357 339 tabplay~ swinger-sound2; #X msg 161 248 read -resize \$1 swinger-sound2; #X connect 1 0 12 0; #X connect 3 0 1 0; #X connect 5 0 11 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 11 0 4 0; #X connect 11 1 6 0; #X connect 12 0 0 0; #X restore 201 73 pd sound2; #X obj 314 128 hsl 128 15 0 1 0 0 empty empty empty -2 -6 0 8 -131603 -1 -1 11500 1; #X text 334 151 gain; #X connect 0 0 3 0; #X connect 1 0 0 2; #X connect 3 0 2 0; #X connect 3 0 2 1; #X connect 5 0 4 0; #X connect 6 0 3 1; #X connect 8 0 0 0; #X connect 9 0 0 1; #X connect 10 0 6 0; fftease-2.5.2.git20121005/swinger~.c0000644000076500007650000002326212067450034015236 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *swinger_class; #endif #if PD static t_class *swinger_class; #endif #define OBJECT_NAME "swinger~" typedef struct _swinger { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int *bitshuffle; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; int overlap;//overlap factor int winfac;// window factor int vs;//last measurement of vector size short mute; } t_swinger; /* msp function prototypes */ void *swinger_new(t_symbol *s, int argc, t_atom *argv); t_int *swinger_perform(t_int *w); void swinger_dsp(t_swinger *x, t_signal **sp, short *count); void swinger_assist(t_swinger *x, void *b, long m, long a, char *s); void swinger_mute(t_swinger *x, t_floatarg state); void swinger_init(t_swinger *x, short initialized); void swinger_dsp_free(t_swinger *x); void swinger_overlap(t_swinger *x, t_floatarg o); void swinger_winfac(t_swinger *x, t_floatarg o); //int fftease_power_of_two(int p); void swinger_fftinfo(t_swinger *x); #if MSP void main(void) { setup((t_messlist **)&swinger_class, (method) swinger_new, (method)dsp_free, (short)sizeof(t_swinger), 0L, A_GIMME, 0); addmess((method)swinger_dsp, "dsp", A_CANT, 0); addmess((method)swinger_assist,"assist",A_CANT,0); addmess((method)swinger_mute,"mute",A_FLOAT,0); addmess((method)swinger_overlap,"overlap",A_FLOAT,0); addmess((method)swinger_winfac,"winfac",A_FLOAT,0); addmess((method)swinger_fftinfo,"fftinfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD /* Pd Initialization */ void swinger_tilde_setup(void) { swinger_class = class_new(gensym("swinger~"), (t_newmethod)swinger_new, (t_method)swinger_dsp_free ,sizeof(t_swinger), 0,A_GIMME,0); CLASS_MAINSIGNALIN(swinger_class, t_swinger, x_f); class_addmethod(swinger_class, (t_method)swinger_dsp, gensym("dsp"), 0); class_addmethod(swinger_class, (t_method)swinger_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(swinger_class, (t_method)swinger_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(swinger_class, (t_method)swinger_winfac, gensym("winfac"), A_DEFFLOAT,0); class_addmethod(swinger_class, (t_method)swinger_fftinfo, gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif /* diagnostic messages for Max */ void swinger_fftinfo(t_swinger *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void swinger_mute(t_swinger *x, t_floatarg state) { x->mute = state; } void swinger_assist (t_swinger *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Signal to be Phase Replaced "); break; case 1: sprintf(dst,"(signal) Signal to Supply Phase Information "); break; } } else { if (msg == 2) sprintf(dst,"(signal) Swinger Output"); } } void *swinger_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_swinger *x = (t_swinger *) newobject(swinger_class); dsp_setup((t_pxobject *)x,2); outlet_new((t_pxobject *)x, "signal"); /* make sure that signal inlets and outlets have their own memory */ x->x_obj.z_misc |= Z_NO_INPLACE; #endif #if PD t_swinger *x = (t_swinger *)pd_new(swinger_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* INITIALIZATIONS */ x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!x->winfac) x->winfac = 1; if(!x->overlap) x->overlap = 4; x->vs = sys_getblksize(); x->R = sys_getsr(); swinger_init(x,0); return (x); } void swinger_overlap(t_swinger *x, t_floatarg o) { if(!fftease_power_of_two(o)){ post("%f is not a power of two",o); return; } x->overlap = o; swinger_init(x,1); } void swinger_winfac(t_swinger *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; swinger_init(x,1); } void swinger_init(t_swinger *x, short initialized) { int i; x->D = x->vs; x->N = x->vs * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) ); x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1);// wants an ODD window } t_int *swinger_perform(t_int *w) { int n, i,j, inCount, R, N, N2, D, Nw, invert = 1, even, odd, *bitshuffle; float maxamp, threshMult = 1., mult, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; t_float *inOne, *inTwo, *out; /* get our inlets and outlets */ t_swinger *x = (t_swinger *) (w[1]); inOne = (t_float *)(w[2]); inTwo = (t_float *)(w[3]); out = (t_float *)(w[4]); n = (int)(w[5]); /* dereference structure */ inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; /* no computation if muted */ if(x->mute){ while(n--) *out++ = 0.0; return w+6; } inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw-D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* use redundant coding for speed, even though moving the invert variable comparison outside of the for loop will give us only a minimal performance increase (hypot and atan2 are the most intensive portions of this code). consider adding a table lookup for atan2 instead. */ /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); /* replace signal one's phases with those of signal two */ *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b2, a2 ); } for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+6); } void swinger_dsp_free( t_swinger *x ) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->inputTwo,0); freebytes(x->bufferOne,0); freebytes(x->bufferTwo,0); freebytes(x->channelOne,0); freebytes(x->channelTwo,0); freebytes(x->output,0); } void swinger_dsp(t_swinger *x, t_signal **sp, short *count) { if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; swinger_init(x,1); } dsp_add(swinger_perform, 5, x, sp[0]->s_vec,sp[1]->s_vec,sp[2]->s_vec,sp[0]->s_n); } fftease-2.5.2.git20121005/taint~-help.pd0000644000076500007650000001071612067450034016006 0ustar hanshans#N canvas 417 69 677 443 10; #X obj 167 237 *~ 1; #X obj 167 289 dac~; #X floatatom 190 218 5 0 0 0 - centerring-gain -; #X msg 18 330 \; pd dsp \$1; #X obj 18 313 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 17 207 hsl 128 15 0 1.5 0 0 centerring-gain empty output_gain -2 -6 0 8 -79789 -1 -1 447 1; #N canvas 0 22 523 358 messages 0; #X obj 132 286 outlet; #X text 302 155 turn on invert; #X msg 132 223 pad \$1; #X floatatom 132 112 5 0 0 0 - - -; #X text 227 108 is turned on; #X obj 281 156 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X msg 281 178 invert \$1; #X text 227 94 pad affects the gain only when "invert"; #X obj 132 142 ampdb; #X obj 132 67 loadbang; #X msg 132 90 -32; #X floatatom 132 167 5 0 0 0 - - -; #X obj 257 256 fftease-system; #X connect 2 0 0 0; #X connect 3 0 8 0; #X connect 5 0 6 0; #X connect 6 0 0 0; #X connect 8 0 11 0; #X connect 9 0 10 0; #X connect 10 0 3 0; #X connect 11 0 2 0; #X connect 12 0 0 0; #X restore 448 167 pd messages; #X obj 18 240 hsl 128 15 0.15 1 0 0 cod-scaling-exponent empty scaling_exponent -2 -6 0 8 -88868 -1 -1 800 1; #X floatatom 236 121 5 0 0 0 - cod-inverse-threshold -; #X floatatom 236 163 5 0 0 0 - - -; #N canvas 990 218 508 397 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array taint-sound1 17642 float 2; #X coords 0 1 17641 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #X msg 31 177 read -resize \$1 taint-sound1; #X obj 227 268 tabplay~ taint-sound1; #X connect 1 0 12 0; #X connect 3 0 1 0; #X connect 5 0 13 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 12 0 0 0; #X connect 13 0 4 0; #X connect 13 1 6 0; #X restore 167 22 pd playsound1; #N canvas 990 218 512 401 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #N canvas 0 22 450 300 graph2 0; #X array taint-sound2 133504 float 2; #X coords 0 1 133503 -1 200 140 1; #X restore 216 15 graph; #X msg 31 177 read -resize \$1 taint-sound2; #X obj 227 268 tabplay~ taint-sound2; #X connect 1 0 12 0; #X connect 2 0 1 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 12 0 0 0; #X connect 13 0 3 0; #X connect 13 1 5 0; #X restore 190 43 pd playsound2; #X floatatom 213 91 5 0.35 2 0 - cod-scaling-exponent -; #X obj 19 278 hsl 128 15 -90 0 0 0 cod-inverse-threshold empty inverse_threshold -2 -6 0 8 -88868 -1 -1 6100 1; #X text 280 136 but only when "invert" is turned on); #X text 213 73 scaling exponent (lower values increase distortion) ; #X text 294 31 <- load and loop two soundfiles to hear effect; #X msg 14 123 0.1 0.3 -36; #X obj 14 139 unpack f f f; #X obj 14 107 loadbang; #X text 275 120 inverse threshold (lower values intensify effect; #N canvas 376 316 478 328 taint-block 0; #X obj 163 185 outlet~; #X obj 163 38 inlet~; #X obj 269 107 inlet; #X obj 201 81 inlet; #X obj 221 98 inlet; #X obj 182 65 inlet~; #X obj 163 128 taint~; #X obj 233 219 block~ 512; #X connect 1 0 6 0; #X connect 2 0 6 0; #X connect 3 0 6 2; #X connect 4 0 6 3; #X connect 5 0 6 1; #X connect 6 0 0 0; #X restore 167 183 pd taint-block; #X obj 236 141 ampdb; #X text 221 262 taint~ multiplies the spectra of two input signals. Multiplication of spectra can cause significant drops in the amplitude of the output signal. The inverse option allows division of the input spectra. Division requires the use of a threshold to avert division by zero. Also \, signal division will cause massive amplitude gains. Be careful of your ears and equipment. Start the amplitude very low (-100dB) and slowly work up to an acceptable level. A pad is provided to balance gain between normal and invert options.; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 2 0 0 1; #X connect 4 0 3 0; #X connect 6 0 21 4; #X connect 8 0 22 0; #X connect 9 0 21 3; #X connect 10 0 21 0; #X connect 11 0 21 1; #X connect 12 0 21 2; #X connect 17 0 18 0; #X connect 18 0 5 0; #X connect 18 1 7 0; #X connect 18 2 13 0; #X connect 19 0 17 0; #X connect 21 0 0 0; #X connect 22 0 9 0; fftease-2.5.2.git20121005/taint~.c0000644000076500007650000003360112067450034014675 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *taint_class; #endif #if PD static t_class *taint_class; #endif #define OBJECT_NAME "taint~" /* Adding -32dB pad for invert option. Also added latency mechanism in switching from normal to "invert" to avoid glitches from extreme amplitude disparities. Made all inlets of type signal (with float options). Threshold input is now linear, not dB (with Max doing the conversion if desired). -EL 10/1/2005 */ typedef struct _taint { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int invert; int *bitshuffle; float threshold; float exponent; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size int invert_countdown; // delay onset of invert effect to avoid loud glitches int invert_nextstate;// next state for invert float invert_pad; } t_taint; /* msp function prototypes */ void *taint_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *taint_perform(t_int *w); void taint_dsp(t_taint *x, t_signal **sp, short *count); void taint_assist(t_taint *x, void *b, long m, long a, char *s); void taint_dest(t_taint *x, double f); void taint_invert(t_taint *x, t_floatarg toggle); void taint_free(t_taint *x); void taint_mute(t_taint *x, t_floatarg toggle); void taint_fftinfo(t_taint *x); void taint_tilde_setup(void); void taint_overlap(t_taint *x, t_floatarg o); void taint_winfac(t_taint *x, t_floatarg o); void taint_init(t_taint *x, short initialized); void taint_pad(t_taint *x, t_floatarg pad); #if MSP void main(void) { setup( (struct messlist **) &taint_class, (void *) taint_new, (method)dsp_free, (short) sizeof(t_taint), 0, A_GIMME, 0); addmess((method)taint_dsp, "dsp", A_CANT, 0); addmess((method)taint_assist,"assist",A_CANT,0); addmess((method)taint_invert,"invert", A_FLOAT, 0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); addmess((method)taint_overlap,"overlap", A_FLOAT, 0); addmess((method)taint_winfac,"winfac", A_FLOAT, 0); addmess((method)taint_mute,"mute", A_FLOAT, 0); addmess((method)taint_pad,"pad", A_FLOAT, 0); addmess((method)taint_fftinfo,"fftinfo", 0); addfloat((method) taint_dest); dsp_initclass(); } /* float input handling routine (MSP only)*/ void taint_dest(t_taint *x, double f) { int inlet = x->x_obj.z_in; if ( inlet == 2 ) { x->exponent = f; } if ( inlet == 3 ){ /* x->threshold = (float) (pow( 10., (f * .05))); */ x->threshold = f; } } #endif #if PD void taint_tilde_setup(void) { taint_class = class_new(gensym("taint~"), (t_newmethod)taint_new, (t_method)taint_free ,sizeof(t_taint), 0,A_GIMME,0); CLASS_MAINSIGNALIN(taint_class, t_taint, x_f); class_addmethod(taint_class, (t_method)taint_dsp, gensym("dsp"), 0); class_addmethod(taint_class, (t_method)taint_assist, gensym("assist"), 0); class_addmethod(taint_class, (t_method)taint_invert, gensym("invert"), A_FLOAT,0); class_addmethod(taint_class, (t_method)taint_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(taint_class, (t_method)taint_mute, gensym("mute"), A_FLOAT,0); class_addmethod(taint_class, (t_method)taint_pad, gensym("pad"), A_FLOAT,0); class_addmethod(taint_class, (t_method)taint_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void taint_mute(t_taint *x, t_floatarg toggle) { x->mute = (short)toggle; // post("mute set to %f, %d",toggle,x->mute); } void taint_overlap(t_taint *x, t_floatarg o) { if(!fftease_power_of_two(o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; taint_init(x,1); } void taint_winfac(t_taint *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; taint_init(x,1); } void taint_fftinfo( t_taint *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void taint_free(t_taint *x) { #if MSP dsp_free((t_pxobject *) x); #endif free(x->trigland); free(x->bitshuffle); free(x->Wanal); free(x->Wsyn); free(x->Hwin); free(x->inputOne); free(x->inputTwo); free(x->bufferOne); free(x->bufferTwo); free(x->channelOne); free(x->channelTwo); free(x->output); } void taint_pad(t_taint *x, t_floatarg pad) { x->invert_pad = pad; taint_invert(x,x->invert);//resubmit to invert } void taint_invert(t_taint *x, t_floatarg toggle) { x->invert_nextstate = toggle; x->invert_countdown = x->overlap; // delay effect for "overlap" vectors if(x->invert_nextstate){ // lower gain immediately; delay going to invert x->mult = (1. / (float) x->N) * x->invert_pad; } else { x->invert = 0; //immediately turn off invert; delay raising gain } } void taint_assist (t_taint *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input One");break; case 1: sprintf(dst,"(signal) Input Two"); break; case 2: sprintf(dst,"(signal/float) Scaling Exponent"); break; case 3: sprintf(dst,"(signal/float) Inverse Threshold"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void *taint_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_taint *x = (t_taint *) newobject(taint_class); dsp_setup((t_pxobject *)x,4); outlet_new((t_pxobject *)x, "signal"); // x->x_obj.z_misc |= Z_NO_INPLACE; // probably not needed #endif #if PD t_taint *x = (t_taint *)pd_new(taint_class); /* add three additional signal inlets */ inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: scaling exponent, threshold (now linear), overlap, winfac */ x->exponent = atom_getfloatarg(0,argc,argv); x->threshold = atom_getfloatarg(1,argc,argv); x->overlap = atom_getfloatarg(2,argc,argv); x->winfac = atom_getfloatarg(3,argc,argv); /* x->threshold = (float) pow(10.0,(x->threshold * .05)); */ /* sanity check */ if(x->exponent < 0.25) x->exponent = 0.25; if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } x->vs = sys_getblksize(); x->R = sys_getsr(); taint_init(x,0); return (x); } void taint_init(t_taint *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->invert_pad = 0.025; // -32 dB x->invert_countdown = 0; x->mute = 0; x->invert = 0; x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) ); x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); } if(x->invert){ x->mult *= x->invert_pad; } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 1); } t_int *taint_perform(t_int *w) { int i,j, inCount, R, N, N2, D, Nw, invert = 0, even, odd, *bitshuffle; float maxamp, threshold = 1., mult, exponent, a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; /* get our inlets and outlets */ t_taint *x = (t_taint *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *vec_exponent = (t_float *)(w[4]); t_float *vec_threshold = (t_float *)(w[5]); t_float *out = (t_float *)(w[6]); t_int n = w[7]; short *connected = x->connected; /* dereference structure */ if(connected[2]) x->exponent = *vec_exponent; if(connected[3]){ x->threshold = *vec_threshold; /* x->threshold = (float) (pow( 10., (x->threshold * .05))); */ } if(x->mute){ while(n--) *out++ = 0.0; return w+8; } // do countdown if(x->invert_countdown > 0){ if(x->invert) { // we } else { } --(x->invert_countdown); if(! x->invert_countdown){ // countdown just ended if(x->invert_nextstate){ // moving to invert (gain is already down) x->invert = x->invert_nextstate; } else { // invert is already off - now reset gain x->mult = 1. / (float) x->N; } } } inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; invert = x->invert; exponent = x->exponent; if ( x->threshold != 0. ) threshold = x->threshold; /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* convert to polar coordinates from complex values */ if (invert) { for ( i = 0; i <= N2; i++ ) { float magnitude; odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); magnitude = *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); /* use threshold for inverse filtering to avoid division by zero */ if ( magnitude < threshold ) magnitude = 0.; else magnitude = 1. / magnitude; *(channelOne+even) *= magnitude; *(channelOne+even) = pow( *(channelOne+even), exponent ); } } else { for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); /* simple multiplication of magnitudes */ *(channelOne+even) *= *(channelTwo+even); *(channelOne+even) = pow( *(channelOne+even), exponent ); } } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* use slow inverse fft */ // rfft( bufferOne, N2, INVERSE ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+8); } void taint_dsp(t_taint *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 4; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 4; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; taint_init(x,1); } dsp_add(taint_perform, 7, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[4]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/thresher~-help.pd0000644000076500007650000000372212067450034016512 0ustar hanshans#N canvas 112 22 568 570 10; #N canvas 0 22 474 324 threshblock 0; #X obj 197 47 inlet; #X obj 234 68 inlet; #X obj 161 29 inlet~; #X obj 161 111 outlet~; #X obj 339 87 block~ 256; #X obj 313 47 inlet; #X obj 161 87 thresher~ 0.1 0.99 4 1; #X connect 0 0 6 1; #X connect 1 0 6 2; #X connect 2 0 6 0; #X connect 5 0 6 0; #X connect 6 0 3 0; #X restore 64 79 pd threshblock; #X obj 66 223 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 64 21 noise~; #X obj 249 206 vsl 15 128 1e-05 0.2 0 0 thresh b threshold 0 -8 0 8 -73688 -1 -1 6350 1; #X obj 300 206 vsl 15 128 0.75 0.999 0 0 damp c damping_factor 0 -8 0 8 -258462 -1 -1 10201 1; #X obj 64 187 dac~; #X obj 64 138 *~ 0.1; #X msg 66 246 \; pd dsp \$1; #X obj 205 206 vsl 15 128 0 4 0 0 amp a amp 0 -8 0 8 -150784 -1 -1 2540 1; #N canvas 0 22 462 312 init 0; #X obj 31 29 loadbang; #X obj 32 71 unpack f f f; #X obj 33 99 s a; #X obj 43 108 s b; #X obj 53 118 s c; #X msg 31 51 0.8 0.1 0.95; #X connect 0 0 5 0; #X connect 1 0 2 0; #X connect 1 1 3 0; #X connect 1 2 4 0; #X connect 5 0 1 0; #X restore 67 286 pd init; #X obj 101 116 nbx 5 14 -1e+37 1e+37 0 0 empty amp empty 0 -6 0 10 -262144 -1 -1 0.8 256; #X obj 126 60 nbx 5 14 -1e+37 1e+37 0 0 empty damp empty 0 -6 0 10 -262144 -1 -1 0.950004 256; #X obj 95 44 nbx 5 14 -1e+37 1e+37 0 0 empty thresh empty 0 -6 0 10 -262144 -1 -1 0.100005 256; #X text 113 20 <- something more interesting could go here.; #X obj 251 63 fftease-system; #X text 54 359 thresher~ sustains the amplitude and frequency in lower-energy FFT bins. The extent of this effect is controlled by the threshold parameter - at 0 all frames pass \, at higher values more frames are sustained. The damping factor controls the decay time - a value of 1 gives an infinite freeze. See also the somewhat more interesting bthresher~.; #X connect 0 0 6 0; #X connect 1 0 7 0; #X connect 2 0 0 0; #X connect 6 0 5 0; #X connect 6 0 5 1; #X connect 10 0 6 1; #X connect 11 0 0 2; #X connect 12 0 0 1; #X connect 14 0 0 3; fftease-2.5.2.git20121005/thresher~.c0000644000076500007650000002666512067450034015416 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *thresher_class; #endif #if PD static t_class *thresher_class; #endif #define OBJECT_NAME "thresher~" #define DEFAULT_HOLD (40.0) typedef struct _thresher { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int in_count; float *Wanal; float *Wsyn; float *input; float *Hwin; // float *winput; float *buffer; float *channel; float *output; /* thresher vars */ float move_threshold; float *composite_frame ; int *frames_left; int max_hold_frames; float max_hold_time; int first_frame; float damping_factor ; short thresh_connected; short damping_connected; // for convert float *c_lastphase_in; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // for fast fft float mult; float *trigland; int *bitshuffle; short mute; short bypass; int winfac; int overlap; float tadv; } t_thresher; void *thresher_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *thresher_perform(t_int *w); void thresher_dsp(t_thresher *x, t_signal **sp, short *count); void thresher_assist(t_thresher *x, void *b, long m, long a, char *s); void thresher_float(t_thresher *x, double f); void thresher_mute(t_thresher *x, t_floatarg f); void thresher_bypass(t_thresher *x, t_floatarg f); void thresher_free( t_thresher *x ); void thresher_overlap(t_thresher *x, t_floatarg f); void thresher_winfac(t_thresher *x, t_floatarg f); void thresher_fftinfo(t_thresher *x); void thresher_init(t_thresher *x, short initialized); #if MSP void main(void) { setup((t_messlist **)&thresher_class, (method)thresher_new, (method)thresher_free, (short)sizeof(t_thresher), 0L, A_GIMME, 0); addmess((method)thresher_dsp, "dsp", A_CANT, 0); addmess((method)thresher_assist,"assist",A_CANT,0); addmess((method)thresher_mute,"mute",A_FLOAT,0); addmess((method)thresher_bypass,"bypass",A_FLOAT,0); addmess((method)thresher_overlap,"overlap",A_DEFFLOAT,0); addmess((method)thresher_winfac,"winfac",A_DEFFLOAT,0); addmess((method)thresher_fftinfo,"fftinfo",0); addfloat((method)thresher_float); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void thresher_tilde_setup(void) { thresher_class = class_new(gensym("thresher~"), (t_newmethod)thresher_new, (t_method)thresher_free ,sizeof(t_thresher), 0,A_GIMME,0); CLASS_MAINSIGNALIN(thresher_class, t_thresher, x_f ); class_addmethod(thresher_class, (t_method)thresher_dsp, gensym("dsp"), 0); class_addmethod(thresher_class, (t_method)thresher_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(thresher_class, (t_method)thresher_bypass, gensym("bypass"), A_DEFFLOAT,0); class_addmethod(thresher_class, (t_method)thresher_assist, gensym("assist"), 0); class_addmethod(thresher_class,(t_method)thresher_overlap,gensym("overlap"),A_FLOAT,0); class_addmethod(thresher_class,(t_method)thresher_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(thresher_class,(t_method)thresher_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void thresher_overlap(t_thresher *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; thresher_init(x,1); } void thresher_winfac(t_thresher *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; thresher_init(x,2); } void thresher_fftinfo(t_thresher *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void thresher_free(t_thresher *x){ #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->c_lastphase_in,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->input,0); freebytes(x->Hwin,0); freebytes(x->buffer,0); freebytes(x->channel,0); freebytes(x->output,0); freebytes(x->composite_frame,0); freebytes(x->frames_left,0); } void thresher_mute(t_thresher *x, t_floatarg f){ x->mute = (short)f; } void thresher_bypass(t_thresher *x, t_floatarg f){ x->bypass = (short)f; } void thresher_assist (t_thresher *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input"); break; case 1: sprintf(dst,"(signal/float) Threshold"); break; case 2: sprintf(dst,"(signal/float) Damping Factor"); break; } } else if (msg==2) { sprintf(dst,"(signal) Output"); } } void *thresher_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_thresher *x = (t_thresher *)newobject(thresher_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_thresher *x = (t_thresher *)pd_new(thresher_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->move_threshold = atom_getfloatarg(0, argc, argv); x->damping_factor = atom_getfloatarg(1, argc, argv); x->overlap = atom_getfloatarg( 2, argc, argv ); x->winfac = atom_getfloatarg( 3, argc, argv ); // post("thresh %f damper %f overlap %d winfac %d", x->move_threshold, x->damping_factor, x->overlap, x->winfac); /* if overlap is zero we crash so should protect against bad input parameters*/ x->D = sys_getblksize(); x->R = sys_getsr(); thresher_init(x,0); return (x); } void thresher_init(t_thresher *x, short initialized) { int i; if(!x->D) x->D = 256; if(!x->R) x->R = 44100; if(!fftease_power_of_two(x->overlap) ) x->overlap = 4; if(!fftease_power_of_two(x->winfac) ) x->winfac = 1; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->in_count = -(x->Nw); x->mult = 1. / (float) x->N; x->tadv = (float) x->D / (float) x->R ; if(!initialized){ x->mute = 0; x->bypass = 0; if(!x->damping_factor){ x->damping_factor = .95; } if(!x->move_threshold){ x->move_threshold = .00001 ; } x->first_frame = 1; x->max_hold_time = DEFAULT_HOLD ; x->max_hold_frames = x->max_hold_time / x->tadv; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; x->Wanal = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Wsyn = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->Hwin = (float *) getbytes( (MAX_Nw) * sizeof(float)); x->input = (float *) getbytes( MAX_Nw * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->buffer = (float *) getbytes( MAX_N * sizeof(float) ); x->channel = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); x->c_lastphase_in = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->c_lastphase_out = (float *) getbytes( (MAX_N2+1) * sizeof(float) ); x->composite_frame = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->frames_left = (int *) getbytes( (MAX_N+2) * sizeof(int) ); } memset((char *)x->input,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); memset((char *)x->frames_left,0,(x->N+2) * sizeof(float)); init_rdft(x->N, x->bitshuffle, x->trigland); makehanning(x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } t_int *thresher_perform(t_int *w) { float sample, outsamp ; int i,j; t_thresher *x = (t_thresher *) (w[1]); float *in = (t_float *)(w[2]); float *inthresh = (t_float *)(w[3]); float *damping = (t_float *)(w[4]); float *out = (t_float *)(w[5]); int n = (int)(w[6]); float *input = x->input; float *output = x->output; float *buffer = x->buffer; float *Wanal = x->Wanal; float *Wsyn = x->Wsyn; float *channel = x->channel; float damping_factor = x->damping_factor; int max_hold_frames = x->max_hold_frames; int *frames_left = x->frames_left; float *composite_frame = x->composite_frame; float *c_lastphase_in = x->c_lastphase_in; float *c_lastphase_out = x->c_lastphase_out; float c_fundamental = x->c_fundamental; float c_factor_in = x->c_factor_in; float c_factor_out = x->c_factor_out; int *bitshuffle = x->bitshuffle; float *trigland = x->trigland; float mult = x->mult; int in_count = x->in_count; int R = x->R; int N = x->N; int N2 = x->N2; int D = x->D; int Nw = x->Nw; float move_threshold = x->move_threshold; if( x->mute ) { for( j = 0; j < D; j++) { *out++ = 0.0 ; } return (w+7); } if ( x->bypass ) { for( j = 0; j < D; j++) { *out++ = *in++ ; } return (w+7); } if( x->thresh_connected ) { move_threshold = *inthresh ; } if( x->damping_connected ) { damping_factor = *damping ; } in_count += D; for ( j = 0 ; j < Nw - D ; j++ ) input[j] = input[j+D]; for ( j = Nw - D; j < Nw; j++ ) { input[j] = *in++; } fold( input, Wanal, Nw, buffer, N, in_count ); rdft( N, 1, buffer, bitshuffle, trigland ); convert( buffer, channel, N2, c_lastphase_in, c_fundamental, c_factor_in ); if( x->first_frame ){ for ( i = 0; i < N+2; i++ ){ composite_frame[i] = channel[i]; frames_left[i] = max_hold_frames; } x->first_frame = 0; } else { for( i = 0; i < N+2; i += 2 ){ if(fabs( composite_frame[i] - channel[i] ) > move_threshold || frames_left[i] <= 0 ){ composite_frame[i] = channel[i]; composite_frame[i+1] = channel[i+1]; frames_left[i] = max_hold_frames; } else { --(frames_left[i]); composite_frame[i] *= damping_factor; } } } unconvert( composite_frame, buffer, N2, c_lastphase_out, c_fundamental, c_factor_out ); rdft( N, -1, buffer, bitshuffle, trigland ); overlapadd( buffer, N, Wsyn, output, Nw, in_count ); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; x->in_count = in_count; x->damping_factor = damping_factor; return (w+7); } #if MSP void thresher_float(t_thresher *x, double f) // Look at floats at inlets { int inlet = x->x_obj.z_in; if (inlet == 1) { x->move_threshold = f; } else if (inlet == 2) { x->damping_factor = f; } } #endif void thresher_dsp(t_thresher *x, t_signal **sp, short *count) { #if MSP x->thresh_connected = count[1]; x->damping_connected = count[2]; #endif #if PD x->thresh_connected = 1; x->damping_connected = 1; #endif if(sp[0]->s_n != x->D || x->R != sp[0]->s_sr){ x->D = sp[0]->s_n; x->R = sp[0]->s_sr; thresher_init(x,1); } dsp_add(thresher_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/unconvert.c0000644000076500007650000000075512067450034015407 0ustar hanshans#include "fftease.h" void unconvert( float *C, float *S, int N2, float *lastphase, float fundamental, float factor ) { int i, real, imag, amp, freq; float mag, phase; double sin(), cos(); for ( i = 0; i <= N2; i++ ) { imag = freq = ( real = amp = i<<1 ) + 1; if ( i == N2 ) real = 1; mag = C[amp]; lastphase[i] += C[freq] - i*fundamental; phase = lastphase[i]*factor; S[real] = mag*cos( phase ); if ( i != N2 ) S[imag] = -mag*sin( phase ); } } fftease-2.5.2.git20121005/vacancy~-help.pd0000644000076500007650000000774712067450034016325 0ustar hanshans#N canvas 606 96 689 455 10; #X obj 167 237 *~ 1; #X obj 167 289 dac~; #X floatatom 190 218 5 0 0 0 - centerring-gain -; #X msg 18 330 \; pd dsp \$1; #X obj 18 313 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X obj 17 207 hsl 128 15 0 1.5 0 0 centerring-gain empty output_gain -2 -6 0 8 -171124 -1 -1 847 1; #N canvas 785 535 531 366 messages 0; #X obj 132 268 outlet; #X text 291 182 turn on invert; #X obj 270 183 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X msg 270 205 invert \$1; #X obj 132 105 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X msg 132 127 swapphase \$1; #X obj 182 172 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X msg 182 194 rms \$1; #X obj 311 252 fftease-system; #X connect 2 0 3 0; #X connect 3 0 0 0; #X connect 4 0 5 0; #X connect 5 0 0 0; #X connect 6 0 7 0; #X connect 7 0 0 0; #X connect 8 0 0 0; #X restore 448 167 pd messages; #X floatatom 238 123 5 0 0 0 - vac-compositing-threshold -; #N canvas 990 218 520 409 playsound1 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array vacancy-sound1 1.09357e+06 float 2; #X coords 0 1 1.09357e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #X msg 31 177 read -resize \$1 vacancy-sound1; #X obj 227 268 tabplay~ vacancy-sound1; #X connect 1 0 12 0; #X connect 3 0 1 0; #X connect 5 0 13 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 12 0 0 0; #X connect 13 0 4 0; #X connect 13 1 6 0; #X restore 167 22 pd playsound1; #N canvas 990 218 524 413 playsound2 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X text 316 205 comment; #N canvas 0 22 450 300 graph2 0; #X array vacancy-sound2 1.764e+06 float 2; #X coords 0 1 1.764e+06 -1 200 140 1; #X restore 216 15 graph; #X msg 31 177 read -resize \$1 vacancy-sound2; #X obj 227 268 tabplay~ vacancy-sound2; #X connect 1 0 12 0; #X connect 2 0 1 0; #X connect 4 0 13 0; #X connect 5 0 4 0; #X connect 6 0 5 1; #X connect 12 0 0 0; #X connect 13 0 3 0; #X connect 13 1 5 0; #X restore 202 45 pd playsound2; #X text 294 31 <- load and loop two soundfiles to hear effect; #X obj 14 107 loadbang; #N canvas 376 316 482 332 vacancy-block 0; #X obj 163 185 outlet~; #X obj 163 38 inlet~; #X obj 269 107 inlet; #X obj 214 87 inlet; #X obj 188 64 inlet~; #X obj 233 219 block~ 512; #X obj 163 128 vacancy~; #X connect 1 0 6 0; #X connect 2 0 6 0; #X connect 3 0 6 2; #X connect 4 0 6 1; #X connect 6 0 0 0; #X restore 167 183 pd vacancy-block; #X text 280 124 compositing threshold; #X obj 16 242 hsl 128 15 -90 90 0 0 vac-compositing-threshold empty compositing_threshold -2 -6 0 8 -171124 -1 -1 3810 1; #X text 221 262 vacancy~ performs spectral compositing. The threshold controls the compositing and is specified in dB. Useful values lie in the range from -90 dB to 90 dB. Threshold inversion is available via the invert message. The threshold can also track the current RMS value of of the signal. In RMS tracking mode \, the useful threshold range will be somewhat different depending upon the character of the input signals. Phases will be derived from the left input unless phase swapping is specified. In this case phases will be taken from the right input signal when the threshold test is true.; #X msg 14 123 0.1 -36; #X obj 14 139 unpack f f; #X connect 0 0 1 0; #X connect 0 0 1 1; #X connect 2 0 0 1; #X connect 4 0 3 0; #X connect 6 0 12 3; #X connect 7 0 12 2; #X connect 8 0 12 0; #X connect 9 0 12 1; #X connect 11 0 16 0; #X connect 12 0 0 0; #X connect 16 0 17 0; #X connect 17 0 5 0; #X connect 17 1 14 0; fftease-2.5.2.git20121005/vacancy~.c0000644000076500007650000003214712067450034015206 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *vacancy_class; #endif #if PD static t_class *vacancy_class; #endif #define OBJECT_NAME "vacancy~" /* Added inlet for compositing threshold, which is now given linearly, not in dB (since Max can do that). -EL 02.10.2005 */ typedef struct _vacancy { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; int inCount; int invert; int useRms; int swapPhase; int *bitshuffle; float threshold; float *Wanal; float *Wsyn; float *inputOne; float *inputTwo; float *Hwin; float *bufferOne; float *bufferTwo; float *channelOne; float *channelTwo; float *output; float mult; float *trigland; short connected[8]; short mute; int overlap;//overlap factor int winfac;//window factor int vs;//vector size } t_vacancy; /* msp function prototypes */ void *vacancy_new(t_symbol *s, int argc, t_atom *argv); t_int *vacancy_perform(t_int *w); void vacancy_dsp(t_vacancy *x, t_signal **sp, short *count); void vacancy_assist(t_vacancy *x, void *b, long m, long a, char *s); void vacancy_dest(t_vacancy *x, double f); void vacancy_rms(t_vacancy *x, t_floatarg f); void vacancy_invert(t_vacancy *x, t_floatarg f); void vacancy_swapphase(t_vacancy *x, t_floatarg f); void vacancy_free(t_vacancy *x); void vacancy_mute(t_vacancy *x, t_floatarg toggle); void vacancy_fftinfo(t_vacancy *x); void vacancy_tilde_setup(void); void vacancy_overlap(t_vacancy *x, t_floatarg o); void vacancy_winfac(t_vacancy *x, t_floatarg o); void vacancy_init(t_vacancy *x, short initialized); #if MSP void main(void) { setup((t_messlist **)&vacancy_class, (method)vacancy_new, (method)vacancy_free, (short) sizeof(t_vacancy), 0, A_GIMME, 0); addmess((method)vacancy_dsp, "dsp", A_CANT, 0); addmess((method)vacancy_assist,"assist",A_CANT,0); addmess((method)vacancy_rms,"rms", A_FLOAT, 0); addmess((method)vacancy_invert,"invert", A_FLOAT, 0); addmess((method)vacancy_swapphase,"swapphase", A_FLOAT, 0); addmess((method)vacancy_mute,"mute", A_FLOAT, 0); addmess((method)vacancy_overlap,"overlap", A_FLOAT, 0); addmess((method)vacancy_winfac,"winfac", A_FLOAT, 0); addmess((method)vacancy_fftinfo,"fftinfo", 0); addfloat((method)vacancy_dest); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } void vacancy_dest(t_vacancy *x, double f) { int inlet = x->x_obj.z_in; if(inlet == 2) x->threshold = (float) f; } #endif #if PD void vacancy_tilde_setup(void) { vacancy_class = class_new(gensym("vacancy~"), (t_newmethod)vacancy_new, (t_method)vacancy_free ,sizeof(t_vacancy), 0,A_GIMME,0); CLASS_MAINSIGNALIN(vacancy_class, t_vacancy, x_f); class_addmethod(vacancy_class, (t_method)vacancy_dsp, gensym("dsp"), 0); class_addmethod(vacancy_class, (t_method)vacancy_assist, gensym("assist"), 0); class_addmethod(vacancy_class, (t_method)vacancy_invert, gensym("invert"), A_FLOAT,0); class_addmethod(vacancy_class, (t_method)vacancy_swapphase, gensym("swapphase"), A_FLOAT,0); class_addmethod(vacancy_class, (t_method)vacancy_overlap, gensym("overlap"), A_FLOAT,0); class_addmethod(vacancy_class, (t_method)vacancy_winfac, gensym("winfac"), A_FLOAT,0); class_addmethod(vacancy_class, (t_method)vacancy_mute, gensym("mute"), A_FLOAT,0); class_addmethod(vacancy_class, (t_method)vacancy_fftinfo, gensym("fftinfo"), A_CANT,0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void vacancy_rms(t_vacancy *x, t_floatarg f) { x->useRms = (int) f; } void vacancy_invert(t_vacancy *x, t_floatarg f) { x->invert = (int) f; } void vacancy_swapphase(t_vacancy *x, t_floatarg f) { x->swapPhase = (int) f; } void vacancy_assist (t_vacancy *x, void *b, long msg, long arg, char *dst) { if (msg == 1) { switch (arg) { case 0: sprintf(dst,"(signal) Input One"); break; case 1: sprintf(dst,"(signal) Input Two"); break; case 2: sprintf(dst,"(signal) Mixing Threshold"); break; } } else { if (msg == 2) sprintf(dst,"(signal) Output"); } } void vacancy_fftinfo( t_vacancy *x ) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void vacancy_mute(t_vacancy *x, t_floatarg toggle) { x->mute = (short)toggle; } void vacancy_overlap(t_vacancy *x, t_floatarg o) { if(!fftease_power_of_two(o)){ error("%f is not a power of two",o); return; } x->overlap = (int)o; vacancy_init(x,1); } void vacancy_winfac(t_vacancy *x, t_floatarg f) { if(!fftease_power_of_two(f)){ error("%f is not a power of two",f); return; } x->winfac = (int)f; vacancy_init(x,1); } void *vacancy_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_vacancy *x = (t_vacancy *) newobject(vacancy_class); dsp_setup((t_pxobject *)x,3); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_vacancy *x = (t_vacancy *)pd_new(vacancy_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif /* optional arguments: overlap, window factor */ x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!fftease_power_of_two(x->overlap)){ x->overlap = 4; } if(!fftease_power_of_two(x->winfac)){ x->winfac = 1; } x->vs = sys_getblksize(); x->R = sys_getsr(); vacancy_init(x,0); return (x); } void vacancy_init(t_vacancy *x, short initialized) { int i; x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; if(!initialized){ x->mute = 0; x->invert = 0; x->threshold = 0.; x->useRms = 1; x->swapPhase = 0; x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputOne = (float *) getbytes( MAX_Nw * sizeof(float) ); x->inputTwo = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bufferOne = (float *) getbytes( MAX_N * sizeof(float) ); x->bufferTwo = (float *) getbytes( MAX_N * sizeof(float) ); x->channelOne = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->channelTwo = (float *) getbytes( (MAX_N+2) * sizeof(float) ); x->output = (float *) getbytes( MAX_Nw * sizeof(float) ); x->bitshuffle = (int *) getbytes( MAX_N * 2 * sizeof( int ) ); x->trigland = (float *) getbytes( MAX_N * 2 * sizeof( float ) ); } memset((char *)x->inputOne,0,x->Nw * sizeof(float)); memset((char *)x->inputTwo,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } void vacancy_free(t_vacancy *x) { #if MSP dsp_free((t_pxobject *) x); #endif freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->inputOne,0); freebytes(x->inputTwo,0); freebytes(x->bufferOne,0); freebytes(x->bufferTwo,0); freebytes(x->channelOne,0); freebytes(x->channelTwo,0); freebytes(x->output,0); } t_int *vacancy_perform(t_int *w) { int i,j, inCount, R, N, N2, D, Nw, invert = 0, useRms = 1, swapPhase = 0, even, odd, *bitshuffle; float maxamp, threshold = .001, mult, useme, rms = 0., a1, b1, a2, b2, *inputOne, *inputTwo, *bufferOne, *bufferTwo, *output, *Wanal, *Wsyn, *channelOne, *channelTwo, *trigland; /* get our inlets and outlets */ t_vacancy *x = (t_vacancy *) (w[1]); t_float *inOne = (t_float *)(w[2]); t_float *inTwo = (t_float *)(w[3]); t_float *vec_threshold = (t_float *)(w[4]); t_float *out = (t_float *)(w[5]); t_int n = (t_int)(w[6]); short *connected = x->connected; if(x->mute){ while(n--) *out++ = 0.0; return w+7; } /* dereference structure */ inputOne = x->inputOne; inputTwo = x->inputTwo; bufferOne = x->bufferOne; bufferTwo = x->bufferTwo; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; channelOne = x->channelOne; channelTwo = x->channelTwo; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; invert = x->invert; useRms = x->useRms; swapPhase = x->swapPhase; threshold = connected[2] ? *vec_threshold : x->threshold; /* a bug?? Threshold could be -90 to 90 (dB) if ( x->threshold > 0. ) threshold = x->threshold; */ /* fill our retaining buffers */ inCount += D; for ( j = 0 ; j < Nw - D ; j++ ) { inputOne[j] = inputOne[j+D]; inputTwo[j] = inputTwo[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { inputOne[j] = *inOne++; inputTwo[j] = *inTwo++; } if (useRms) { rms = 0.; for ( i=0; i < Nw; i++ ) rms += *(inputOne+i) * *(inputOne+i); rms = sqrt( rms / Nw ); useme = rms * threshold; } else useme = threshold; /* apply hamming window and fold our window buffer into the fft buffer */ fold( inputOne, Wanal, Nw, bufferOne, N, inCount ); fold( inputTwo, Wanal, Nw, bufferTwo, N, inCount ); /* do an fft */ rdft( N, 1, bufferOne, bitshuffle, trigland ); rdft( N, 1, bufferTwo, bitshuffle, trigland ); /* use slow fft */ // rfft( bufferOne, N2, FORWARD ); // rfft( bufferTwo, N2, FORWARD ); /* convert to polar coordinates from complex values */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; a1 = ( i == N2 ? *(bufferOne+1) : *(bufferOne+even) ); b1 = ( i == 0 || i == N2 ? 0. : *(bufferOne+odd) ); a2 = ( i == N2 ? *(bufferTwo+1) : *(bufferTwo+even) ); b2 = ( i == 0 || i == N2 ? 0. : *(bufferTwo+odd) ); *(channelOne+even) = hypot( a1, b1 ); *(channelOne+odd) = -atan2( b1, a1 ); *(channelTwo+even) = hypot( a2, b2 ); *(channelTwo+odd) = -atan2( b2, a2 ); } /* composite here please */ if (invert) { if (swapPhase) { for ( i=0; i < N2; i+=2 ) { if ( *(channelOne+i) > useme && *(channelTwo+i) < *(channelOne+i) ) { *(channelOne+i) = *(channelTwo+i); *(channelOne+i+1) = *(channelTwo+i+1); } } } else { for ( i=0; i < N2; i+=2 ) { if ( *(channelOne+i) > useme && *(channelTwo+i) < *(channelOne+i) ) { *(channelOne+i) = *(channelTwo+i); if ( *(channelOne+i+1) == 0. ) *(channelOne+i+1) = *(channelTwo+i+1); } } } } else { if (swapPhase) { for ( i=0; i < N2; i+=2 ) { if ( *(channelOne+i) < useme && *(channelTwo+i) > *(channelOne+i) ) { *(channelOne+i) = *(channelTwo+i); *(channelOne+i+1) = *(channelTwo+i+1); } } } else { for ( i=0; i < N2; i+=2 ) { if ( *(channelOne+i) < useme && *(channelTwo+i) > *(channelOne+i) ) { *(channelOne+i) = *(channelTwo+i); if ( *(channelOne+i+1) == 0. ) *(channelOne+i+1) = *(channelTwo+i+1); } } } } /* convert back to complex form, read for the inverse fft */ for ( i = 0; i <= N2; i++ ) { odd = ( even = i<<1 ) + 1; *(bufferOne+even) = *(channelOne+even) * cos( *(channelOne+odd) ); if ( i != N2 ) *(bufferOne+odd) = -(*(channelOne+even)) * sin( *(channelOne+odd) ); } /* do an inverse fft */ rdft( N, -1, bufferOne, bitshuffle, trigland ); /* dewindow our result */ overlapadd( bufferOne, N, Wsyn, output, Nw, inCount); /* set our output and adjust our retaining output buffer */ for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount % Nw; return (w+7); } void vacancy_dsp(t_vacancy *x, t_signal **sp, short *count) { long i; #if MSP for( i = 0; i < 3; i++ ){ x->connected[i] = count[i]; } #endif /* signal is always connected in Pd */ #if PD for( i = 0; i < 3; i++ ){ x->connected[i] = 1; } #endif /* reinitialize if vector size or sampling rate has been changed */ if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; vacancy_init(x,1); } dsp_add(vacancy_perform, 6, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, sp[0]->s_n); } fftease-2.5.2.git20121005/xsyn~-help.pd0000644000076500007650000000412312067450034015663 0ustar hanshans#N canvas 236 558 603 436 10; #X obj 25 136 dac~; #N canvas 0 22 470 320 rich-harmonic-source 0; #X obj 127 232 outlet~; #X obj 127 125 phasor~ 100; #X obj 212 126 phasor~ 125; #X obj 296 125 phasor~ 150; #X obj 127 183 *~ 0.3; #X floatatom 127 67 5 0 0 0 - - -; #X obj 212 99 * 1.25; #X obj 296 100 * 1.5; #X obj 130 34 hsl 128 15 60 600 0 0 empty empty empty -2 -6 0 8 -154413 -1 -1 6350 1; #X msg 127 11 330; #X obj 127 -18 loadbang; #X connect 1 0 4 0; #X connect 2 0 4 0; #X connect 3 0 4 0; #X connect 4 0 0 0; #X connect 5 0 6 0; #X connect 5 0 1 0; #X connect 5 0 7 0; #X connect 6 0 2 0; #X connect 7 0 3 0; #X connect 8 0 5 0; #X connect 9 0 8 0; #X connect 10 0 9 0; #X restore 25 23 pd rich-harmonic-source; #N canvas 473 320 623 326 vocal-source 0; #X obj 31 194 soundfiler; #X obj 31 160 openpanel; #N canvas 0 22 450 300 graph1 0; #X array xsyn-sound1 4e+06 float 2; #X coords 0 1 4e+06 -1 200 140 1; #X restore 237 13 graph; #X msg 31 131 bang; #X obj 227 284 outlet~; #X msg 227 244 bang; #X obj 348 228 spigot; #X obj 385 205 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 1 1; #X text 63 132 open the sound; #X text 133 244 then play it; #X text 304 190 loop if you like; #X obj 227 268 tabplay~ xsyn-sound1; #X msg 31 177 read -resize \$1 xsyn-sound1; #X connect 1 0 12 0; #X connect 3 0 1 0; #X connect 5 0 11 0; #X connect 6 0 5 0; #X connect 7 0 6 1; #X connect 11 0 4 0; #X connect 11 1 6 0; #X connect 12 0 0 0; #X restore 68 46 pd vocal-source; #X msg 34 242 \; pd dsp \$1; #X obj 34 221 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #N canvas 172 351 466 316 xsyn-block 0; #X obj 161 178 outlet~; #X obj 161 49 inlet~; #X obj 283 102 inlet; #X obj 161 213 block~ 256; #X obj 205 72 inlet~; #X obj 161 132 xsyn~ 4; #X connect 1 0 5 0; #X connect 2 0 5 0; #X connect 4 0 5 1; #X connect 5 0 0 0; #X restore 25 88 pd xsyn-block; #X obj 111 68 fftease-system; #X text 34 284 xsyn~ filters the first input with the second input \, creating a spectral cross synthesis effect.; #X connect 1 0 5 0; #X connect 2 0 5 1; #X connect 4 0 3 0; #X connect 5 0 0 0; #X connect 5 0 0 1; #X connect 6 0 5 2; fftease-2.5.2.git20121005/xsyn~.c0000644000076500007650000002201412067450034014553 0ustar hanshans#include "MSPd.h" #include "fftease.h" #if MSP void *xsyn_class; #endif #if PD static t_class *xsyn_class; #endif #define OBJECT_NAME "xsyn~" typedef struct _xsyn { #if MSP t_pxobject x_obj; #endif #if PD t_object x_obj; float x_f; #endif int R; int N; int N2; int Nw; int Nw2; int D; int i; float *input1; float *buffer1; float *channel1; float *input2; float *buffer2; float *channel2; // int inCount; float *Hwin; float *Wanal; float *Wsyn; float *output; /* xsyn vars */ float *c_lastphase_in1; float *c_lastphase_in2; float *c_lastphase_out; float c_fundamental; float c_factor_in; float c_factor_out; // float *filter ; // for fast fft float mult; float *trigland; int *bitshuffle; int overlap;//overlap factor int winfac;//window factor int vs;//vector size short mute;//flag } t_xsyn; void *xsyn_new(t_symbol *s, int argc, t_atom *argv); t_int *offset_perform(t_int *w); t_int *xsyn_perform(t_int *w); void xsyn_dsp(t_xsyn *x, t_signal **sp, short *count); void xsyn_assist(t_xsyn *x, void *b, long m, long a, char *s); void xsyn_dsp_free( t_xsyn *x ); void xsyn_init(t_xsyn *x, short initialized); void xsyn_mute(t_xsyn *x, t_floatarg toggle); void xsyn_fftinfo(t_xsyn *x); void xsyn_overlap(t_xsyn *x, t_floatarg f); void xsyn_winfac(t_xsyn *x, t_floatarg f); void xsyn_dsp_free( t_xsyn *x ) { #if MSP dsp_free( (t_pxobject *) x); #endif freebytes(x->c_lastphase_in1,0); freebytes(x->c_lastphase_in2,0); freebytes(x->c_lastphase_out,0); freebytes(x->trigland,0); freebytes(x->bitshuffle,0); freebytes(x->Wanal,0); freebytes(x->Wsyn,0); freebytes(x->Hwin,0); freebytes(x->input1,0); freebytes(x->buffer1,0); freebytes(x->channel1,0); freebytes(x->input2,0); freebytes(x->buffer2,0); freebytes(x->channel2,0); freebytes(x->output,0); } #if MSP void main(void) { setup((t_messlist **)&xsyn_class, (method) xsyn_new, (method)xsyn_dsp_free, (short)sizeof(t_xsyn), 0, A_GIMME, 0); addmess((method)xsyn_dsp, "dsp", A_CANT, 0); addmess((method)xsyn_assist,"assist",A_CANT,0); addmess((method)xsyn_mute,"mute",A_FLOAT,0); addmess((method)xsyn_overlap,"overlap",A_FLOAT,0); addmess((method)xsyn_winfac,"winfac",A_DEFFLOAT,0); addmess((method)xsyn_fftinfo,"fftinfo",0); dsp_initclass(); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif #if PD void xsyn_tilde_setup(void) { xsyn_class = class_new(gensym("xsyn~"), (t_newmethod)xsyn_new, (t_method)xsyn_dsp_free ,sizeof(t_xsyn), 0,A_GIMME,0); CLASS_MAINSIGNALIN(xsyn_class, t_xsyn, x_f); class_addmethod(xsyn_class, (t_method)xsyn_dsp, gensym("dsp"), 0); class_addmethod(xsyn_class, (t_method)xsyn_assist, gensym("assist"), 0); class_addmethod(xsyn_class, (t_method)xsyn_mute, gensym("mute"), A_DEFFLOAT,0); class_addmethod(xsyn_class, (t_method)xsyn_overlap, gensym("overlap"), A_DEFFLOAT,0); class_addmethod(xsyn_class,(t_method)xsyn_winfac,gensym("winfac"),A_FLOAT,0); class_addmethod(xsyn_class,(t_method)xsyn_fftinfo,gensym("fftinfo"),0); post("%s %s",OBJECT_NAME,FFTEASE_ANNOUNCEMENT); } #endif void xsyn_mute(t_xsyn *x, t_floatarg toggle) { x->mute = (short)toggle; } void xsyn_overlap(t_xsyn *x, t_floatarg f) { int i = (int) f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->overlap = i; xsyn_init(x,1); } void xsyn_winfac(t_xsyn *x, t_floatarg f) { int i = (int)f; if(!fftease_power_of_two(i)){ error("%f is not a power of two",f); return; } x->winfac = i; xsyn_init(x,2); } void xsyn_fftinfo(t_xsyn *x) { if( ! x->overlap ){ post("zero overlap!"); return; } post("%s: FFT size %d, hopsize %d, windowsize %d", OBJECT_NAME, x->N, x->N/x->overlap, x->Nw); } void xsyn_assist (t_xsyn *x, void *b, long msg, long arg, char *dst) { if (msg==1) { switch (arg) { case 0: sprintf(dst,"(signal) Input 1 "); break; case 1: sprintf(dst,"(signal) Input 2 "); break; } } else if (msg==2) { sprintf(dst,"(signal) Output "); } } void *xsyn_new(t_symbol *s, int argc, t_atom *argv) { #if MSP t_xsyn *x = (t_xsyn *)newobject(xsyn_class); dsp_setup((t_pxobject *)x,2); outlet_new((t_pxobject *)x, "signal"); #endif #if PD t_xsyn *x = (t_xsyn *)pd_new(xsyn_class); inlet_new(&x->x_obj, &x->x_obj.ob_pd,gensym("signal"), gensym("signal")); outlet_new(&x->x_obj, gensym("signal")); #endif x->overlap = atom_getfloatarg(0,argc,argv); x->winfac = atom_getfloatarg(1,argc,argv); if(!fftease_power_of_two(x->overlap)) x->overlap = 4; if(!fftease_power_of_two(x->winfac)) x->winfac = 1; x->R = sys_getsr(); x->vs = sys_getblksize(); xsyn_init(x,0); return (x); } void xsyn_init(t_xsyn *x, short initialized) { x->D = x->vs; x->N = x->D * x->overlap; x->Nw = x->N * x->winfac; limit_fftsize(&x->N,&x->Nw,OBJECT_NAME); x->N2 = (x->N)>>1; x->Nw2 = (x->Nw)>>1; x->inCount = -(x->Nw); x->mult = 1. / (float) x->N; x->c_fundamental = (float) x->R/( (x->N2)<<1 ); x->c_factor_in = (float) x->R/((float)x->D * TWOPI); x->c_factor_out = TWOPI * (float) x->D / (float) x->R; if(!initialized){ x->mute = 0; x->Wanal = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Wsyn = (float *) getbytes( MAX_Nw * sizeof(float) ); x->Hwin = (float *) getbytes( MAX_Nw * sizeof(float) ); x->input1 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer1 = (float *) getbytes(MAX_N * sizeof(float)); x->channel1 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->input2 = (float *) getbytes(MAX_Nw * sizeof(float)); x->buffer2 = (float *) getbytes(MAX_N * sizeof(float)); x->channel2 = (float *) getbytes((MAX_N+2) * sizeof(float)); x->output = (float *) getbytes(MAX_Nw * sizeof(float)); x->bitshuffle = (int *) getbytes(MAX_N * 2 * sizeof(int)); x->trigland = (float *) getbytes(MAX_N * 2 * sizeof(float)); x->c_lastphase_in1 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_in2 = (float *) getbytes((MAX_N2+1) * sizeof(float)); x->c_lastphase_out = (float *) getbytes((MAX_N2+1) * sizeof(float)); } memset((char *)x->input1,0,x->Nw * sizeof(float)); memset((char *)x->input2,0,x->Nw * sizeof(float)); memset((char *)x->output,0,x->Nw * sizeof(float)); memset((char *)x->c_lastphase_in1,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_in2,0,(x->N2+1) * sizeof(float)); memset((char *)x->c_lastphase_out,0,(x->N2+1) * sizeof(float)); init_rdft( x->N, x->bitshuffle, x->trigland); makehanning( x->Hwin, x->Wanal, x->Wsyn, x->Nw, x->N, x->D, 0); } t_int *xsyn_perform(t_int *w) { t_float *in1,*out, *in2; float sample, outsamp ; float *input1, *input2, *output, *buffer1, *buffer2, *Wanal, *Wsyn, *channel1, *channel2; int n, i,j, inCount, R, N, N2, D, Nw; float maxamp ; int *bitshuffle; float *trigland; float mult; float a1, a2, b1, b2; int even, odd; t_xsyn *x = (t_xsyn *) (w[1]); in1 = (t_float *)(w[2]); in2 = (t_float *)(w[3]); out = (t_float *)(w[4]); n = (int)(w[5]); /* dereference struncture */ input1 = x->input1; input2 = x->input2; buffer1 = x->buffer1; buffer2 = x->buffer2; inCount = x->inCount; R = x->R; N = x->N; N2 = x->N2; D = x->D; Nw = x->Nw; Wanal = x->Wanal; Wsyn = x->Wsyn; output = x->output; buffer1 = x->buffer1; buffer2 = x->buffer2; channel1 = x->channel1; channel2 = x->channel2; bitshuffle = x->bitshuffle; trigland = x->trigland; mult = x->mult; if(x->mute){ while(n--){ *out++ = 0.0; } return (w+6); } x->inCount += D; for ( j = 0 ; j < Nw - D ; j++ ){ input1[j] = input1[j+D]; input2[j] = input2[j+D]; } for ( j = Nw - D; j < Nw; j++ ) { input1[j] = *in1++; input2[j] = *in2++; } fold( input1, Wanal, Nw, buffer1, N, inCount ); fold( input2, Wanal, Nw, buffer2, N, inCount ); rdft( N, 1, buffer1, bitshuffle, trigland ); rdft( N, 1, buffer2, bitshuffle, trigland ); leanconvert( buffer1, channel1, N2 ); leanconvert( buffer2, channel2, N2 ); maxamp = 0 ; for( i = 0; i < N; i+= 2 ) { if( channel2[i] > maxamp ) { maxamp = channel2[i]; } } if( maxamp == 0.0 ) maxamp = 1.0 ; for( i = 0; i < N; i+= 2 ) { channel1[i] *= (channel2[i] / maxamp ); } leanunconvert( channel1, buffer1, N2 ); rdft( N, -1, buffer1, bitshuffle, trigland ); overlapadd( buffer1, N, Wsyn, output, Nw, inCount); for ( j = 0; j < D; j++ ) *out++ = output[j] * mult; for ( j = 0; j < Nw - D; j++ ) output[j] = output[j+D]; for ( j = Nw - D; j < Nw; j++ ) output[j] = 0.; /* restore state variables */ x->inCount = inCount; return (w+6); } void xsyn_dsp(t_xsyn *x, t_signal **sp, short *count) { if(x->vs != sp[0]->s_n || x->R != sp[0]->s_sr ){ x->vs = sp[0]->s_n; x->R = sp[0]->s_sr; xsyn_init(x,1); } dsp_add(xsyn_perform, 5, x, sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); }