aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2006-09-20 11:22:29 +0000
committerIOhannes m zmölnig <zmoelnig@users.sourceforge.net>2006-09-20 11:22:29 +0000
commit6c61b72cc7be59138b59b1d64b64377fc5c54395 (patch)
tree10bb031fabe7b578a38d6cc8533bd45785fea0af
library providing FFT-objects using the (fast!) libFFTWsvn2git-root
svn path=/trunk/externals/fftw/; revision=5978
-rw-r--r--LICENSE.txt30
-rw-r--r--Makefile3
-rw-r--r--Makefile.in97
-rw-r--r--README.txt31
-rw-r--r--configure.ac220
-rw-r--r--fftw_config.h2
-rw-r--r--fftw_config.h.in1
-rw-r--r--fftw~-help.pd7
-rw-r--r--fftw~.c71
-rw-r--r--fftw~.h24
-rw-r--r--fftw~.pd12
-rw-r--r--ifftw~-help.pd7
-rw-r--r--ifftw~.c71
-rw-r--r--ifftw~.pd12
-rw-r--r--rfftw~-help.pd7
-rw-r--r--rfftw~.c81
-rw-r--r--rfftw~.pd10
-rw-r--r--rifftw~-help.pd7
-rw-r--r--rifftw~.c80
-rw-r--r--rifftw~.pd10
20 files changed, 783 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..a56a51e
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,30 @@
+This software is copyrighted by Miller Puckette and others. The following
+terms (the "Standard Improved BSD License") apply to all files associated with
+the software unless explicitly disclaimed in individual files:
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+3. The name of the author may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..0551fa8
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,3 @@
+
+default:
+ ./configure && make
diff --git a/Makefile.in b/Makefile.in
new file mode 100644
index 0000000..44edfa7
--- /dev/null
+++ b/Makefile.in
@@ -0,0 +1,97 @@
+LIBNAME =fftw~
+VERSION =0.1
+
+PREFIX =@prefix@@PDLIBDIR@
+
+INSTALL_BIN=$(PREFIX)/extra
+
+EXT = @EXT@
+DEFS = @DFLAGS@ -DVERSION=\"$(VERSION)\"
+IFLAGS = -I. @INCLUDES@ $(INCLUDES)
+
+CC = @CC@
+LD = @LD@
+STRIP = @STRIP@ @STRIPFLAGS@
+
+AFLAGS =
+LFLAGS = @LFLAGS@
+WFLAGS =
+
+MAKEDEP_FLAGS = @MAKEDEP_FLAGS@
+
+TARNAME = $(LIBNAME)-@VERSION@.tgz
+BINTARNAME = $(LIBNAME)-@VERSION@-bin.tgz
+
+.SUFFIXES: .$(EXT)
+
+CFLAGS = $(DEFS) $(IFLAGS) $(WFLAGS) @CFLAGS@
+
+LIBS = @LIBS@
+
+SOURCES=$(sort $(filter %.c, $(wildcard *.c)))
+OTARGETS = $(SOURCES:.c=.o)
+TARGETS = $(SOURCES:.c=.$(EXT))
+
+
+
+ifeq (,$(findstring fftw3, $(LIBS) ))
+all:
+ @echo "nothing to be done (no fftw3)"
+
+else
+all: $(TARGETS)
+
+endif
+
+clean:
+ -rm -f *.o *.d
+
+binclean:
+ -rm -f *.$(EXT)
+
+distclean: clean binclean
+ -rm -f *~ _* config.*
+ -rm -rf autom4te.cache
+
+install: install-bin install-doc
+
+install-bin: all
+ -install -d $(INSTALL_BIN)
+ -install -m 644 *.$(EXT) $(INSTALL_BIN)
+
+install-doc:
+ -install -d $(INSTALL_BIN)
+ -install -m 644 *.pd $(INSTALL_BIN)
+
+dist: distclean
+ (cd ..;tar czvf $(TARNAME) $(LIBNAME))
+
+distbin: distclean all clean
+ (cd ..; tar cvzf $(BINTARNAME) $(LIBNAME))
+
+everything: clean all install distclean
+
+%.$(EXT): %.o
+ $(LD) $(LFLAGS) -o $@ *.o $(LIBS)
+ $(STRIP) $@
+
+
+$(LIBNAME): $(OTARGETS)
+ $(LD) $(LFLAGS) -o $(LIBNAME).$(EXT) *.o $(LIBS)
+ $(STRIP) $(LIBNAME).$(EXT)
+
+## dependencies: as proposed by the GNU-make documentation
+## see http://www.gnu.org/software/make/manual/html_node/make_47.html#SEC51
+-include $(SOURCES:.c=.d)
+%.d: %.c
+ @set -e; rm -f $@; \
+ $(CC) $(MAKEDEP_FLAGS) $(CFLAGS) $< > $@.$$$$; \
+ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
+ rm -f $@.$$$$
+
+configure: configure.ac
+ autoconf
+
+Makefile: Makefile.in configure
+ ./configure
+
diff --git a/README.txt b/README.txt
new file mode 100644
index 0000000..fac8caf
--- /dev/null
+++ b/README.txt
@@ -0,0 +1,31 @@
+fftw~ - FFT objects for pd
+
+a set of alternative fft~-objects, using the fftw-library.
+these objects should behave exactly like the original ones:
+
+[fftw~] <-> [fft~]
+[ifftw~] <-> [ifft~]
+[rfftw~] <-> [rfft~]
+[rifftw~] <-> [rifft~]
+
+
+REASONING:
+ the code in here has originally been written by tim blechmann and was
+ meant to be part of pd itself.
+ since miller puckette is somewhat reluctant to integrate these fftw-enabled
+ objects into vanilla pd, this library provides another way to get
+ high-performance FFTs.
+
+TODO:
+ search for a way to override the default FFT-objects in pd with these.
+ (i think cyclone uses such a mechanism)
+
+
+AUTHORS:
+ tim blechmann
+ IOhannes m zmölnig
+
+LICENSING:
+ since this code was originally meant to be part of pd, it is licensed under the
+ same license as pd itself.
+ see LICENSE.txt for details
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..c6602d5
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,220 @@
+dnl Process this file with autoconf to produce a configure script.
+AC_INIT(fftw_config.h.in)
+
+AC_CONFIG_HEADER(fftw_config.h)
+
+dnl Checks for programs.
+AC_PROG_CC
+
+AC_SUBST(STK)
+AC_SUBST(DFLAGS)
+AC_SUBST(LFLAGS)
+AC_SUBST(EXT)
+AC_SUBST(LD)
+AC_SUBST(STRIP)
+AC_SUBST(STRIPFLAGS)
+AC_SUBST(REFERENCEPATH)
+AC_SUBST(PDLIBDIR)
+AC_SUBST(INCLUDES)
+AC_SUBST(VERSION)
+AC_SUBST(HAVE_LIBFFTW3F)
+
+
+AC_ARG_WITH(pdversion, [ --with-pdversion=<ver> enforce a certain pd-version (e.g. 0.37)])
+AC_ARG_WITH(extension, [ --with-extension=<ext> enforce a certain extension for the dynamic library (e.g. dll)])
+
+
+dnl Checks for libraries.
+dnl Replace `main' with a function in -lc:
+AC_CHECK_LIB(c, main)
+AC_CHECK_LIB(crtdll, fclose)
+
+dnl Replace `main' with a function in -lm:
+AC_CHECK_LIB(m, main)
+dnl Replace `main' with a function in -lpthread:
+dnl AC_CHECK_LIB(pthread, main)
+dnl Replace `main' with a function in -lstk:
+dnl AC_CHECK_LIB(stk, main, STK=yes)
+
+
+AC_CHECK_LIB(fftw3f, fftwf_execute)
+
+if test "x$includedir" != "x"; then
+ for id in $includedir
+ do
+ if test -d $id; then INCLUDES="-I$id $INCLUDES"; fi
+ done
+fi
+if test "x$libdir" != "x"; then
+ for id in $libdir
+ do
+ if test -d $id; then LIBS="-L$id $LIBS"; fi
+ done
+fi
+
+AC_CHECK_LIB(pd, nullfn)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_CHECK_HEADERS(stdlib.h stdio.h string.h math.h time.h sys/time.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_FUNC_MMAP
+AC_CHECK_FUNCS(select socket strerror)
+
+dnl check for "-mms-bitfields" cflag
+dnl why is there no generic compiler-check for a given flag ?
+dnl it would make things so easy: AC_CHECK_FLAG([-mms-bitfields],,)
+AC_MSG_CHECKING("ms-bitfields")
+cat > conftest.c << EOF
+int main(){
+ return 0;
+}
+EOF
+if ${CC} ${INCLUDES} ${DFLAGS} -o conftest.o conftest.c ${CFLAGS} -mms-bitfields > /dev/null 2>&1
+then
+ echo "yes"
+ CFLAGS="${CFLAGS} -mms-bitfields"
+else
+ echo "no"
+fi
+
+
+### make-depend flags
+if test "x$ac_cv_c_compiler_gnu" = "xyes"; then
+ AC_SUBST(MAKEDEP_FLAGS, "-MM")
+else
+ AC_SUBST(MAKEDEP_FLAGS, "-M")
+fi
+
+dnl isn't there a better way to check for good linker/stripper ?
+
+dnl if we don't have $LD set, we set it to $(CC)
+dnl LD=${LD:=$CC}
+AC_CHECK_TOOL([LD], [ld], [${CC}])
+
+dnl if we don't have $STRIP set, we set it to ${host}-strip or strip
+
+dnl if we don't have $STRIP set, we set it to ${host}-strip or strip
+AC_CHECK_TOOL([STRIP], [strip], [true])
+AC_MSG_CHECKING([if strip is GNU strip])
+if $STRIP -V | grep GNU > /dev/null
+then
+ AC_SUBST(STRIPFLAGS, "--strip-unneeded")
+ AC_MSG_RESULT([yes])
+else
+ AC_SUBST(STRIPFLAGS,"-x")
+ AC_MSG_RESULT([no])
+fi
+
+dnl
+dnl OK, checks for machines are here now
+dnl
+if test `uname -s` = Linux;
+then
+ LFLAGS="-export_dynamic -shared"
+ CFLAGS="-fPIC $CFLAGS"
+ EXT=pd_linux
+fi
+
+dnl This should use '-bundle_loader /path/to/pd/bin/pd' instead of'-undefined suppress'
+dnl then strip might do something
+if test `uname -s` = Darwin;
+then
+ LD=cc
+ LFLAGS="-bundle -undefined suppress -flat_namespace"
+ EXT=pd_darwin
+ STRIPFLAGS=
+fi
+
+if test `uname | sed -e 's/^MINGW.*/NT/'` = NT;
+then
+ LD=gcc
+ INCLUDES="-I@prefix@/src"
+ DFLAGS="-D__WIN32__ ${DFLAGS}"
+ LFLAGS="-shared @prefix@/bin/pd.dll"
+ EXT=dll
+else
+ PDLIBDIR="/lib/pd"
+fi
+
+if test `uname -s` = IRIX64;
+then
+ LFLAGS="-n32 -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
+ -OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
+ -shared -rdata_shared"
+ EXT=pd_irix6
+ dnl DFLAGS="-DUNIX -DIRIX6 ${DFLAGS}"
+ STRIPFLAGS="--strip-unneeded"
+fi
+
+if test `uname -s` = IRIX32;
+then
+ LFLAGS="-o32 -DUNIX -DIRIX -O2
+ -shared -rdata_shared"
+ EXT=pd_irix5
+ dnl DFLAGS="-DUNIX -DIRIX5 ${DFLAGS}"
+ STRIPFLAGS="--strip-unneeded"
+fi
+
+
+if test "x$with_extension" != "x"
+then
+ EXT=$with_extension
+fi
+
+
+dnl Checks for pd-version, to set the correct help-path
+AC_MSG_CHECKING("pd\>=0.37")
+
+if test "$with_pdversion" != ""
+then
+echo -n "($with_pdversion)... "
+ PD_VERSION="$with_pdversion"
+else
+if test "x$cross_compiling" = "xno"
+then
+
+cat > conftest.c << EOF
+#include <stdio.h>
+#include "m_pd.h"
+int main(){
+ printf("%d.%d\n", PD_MAJOR_VERSION, PD_MINOR_VERSION);
+ return 0;
+}
+EOF
+
+ if $CC $INCLUDES -o conftest.o conftest.c > /dev/null 2>&1
+ then
+ PD_VERSION=`./conftest.o`
+ else
+ PD_VERSION=""
+ fi
+ echo -n $PD_VERSION
+else
+dnl we are cross-compiling...
+ echo -n "(X)..."
+ PD_VERSION="0.38"
+fi
+fi
+
+let PD_MAJORVERSION=`echo $PD_VERSION | cut -d"." -f1`+0
+let PD_MINORVERSION=`echo $PD_VERSION | cut -d"." -f2`+0
+
+
+
+if test "$PD_MAJORVERSION" -gt 0 || test "$PD_MINORVERSION" -ge 37
+then
+ REFERENCEPATH=extra/help-
+ echo " yes"
+else
+ REFERENCEPATH=doc/5.reference/
+ echo " no"
+fi
+
+AC_OUTPUT(Makefile)
+
+rm -f conftest.*
diff --git a/fftw_config.h b/fftw_config.h
new file mode 100644
index 0000000..aab0494
--- /dev/null
+++ b/fftw_config.h
@@ -0,0 +1,2 @@
+/* fftw_config.h. Generated from fftw_config.h.in by configure. */
+#define HAVE_LIBFFTW3F 1
diff --git a/fftw_config.h.in b/fftw_config.h.in
new file mode 100644
index 0000000..efa052b
--- /dev/null
+++ b/fftw_config.h.in
@@ -0,0 +1 @@
+#undef HAVE_LIBFFTW3F
diff --git a/fftw~-help.pd b/fftw~-help.pd
new file mode 100644
index 0000000..83506ca
--- /dev/null
+++ b/fftw~-help.pd
@@ -0,0 +1,7 @@
+#N canvas 99 336 541 313 10;
+#X obj 164 93 fftw~;
+#X text 87 56 forward complex FFT using libFFTW;
+#X text 88 136 this object is a drop-in replacement for pd's built-in
+fft-object;
+#X text 105 205 for help see;
+#X obj 213 204 fft~;
diff --git a/fftw~.c b/fftw~.c
new file mode 100644
index 0000000..bde1a20
--- /dev/null
+++ b/fftw~.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 1997-1999 Miller Puckette and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include "fftw~.h"
+
+#ifdef HAVE_LIBFFTW3F
+
+/* Support for fftw3 by Tim Blechmann */
+
+/* ------------------------ fft~ -------------------------------- */
+static t_class *sigfftw_class;
+
+typedef struct fftw
+{
+ t_object x_obj;
+ float x_f;
+
+ fftwf_plan plan;
+ fftwf_iodim dim;
+} t_sigfftw;
+
+static void *sigfftw_new(void)
+{
+ t_sigfftw *x = (t_sigfftw *)pd_new(sigfftw_class);
+ outlet_new(&x->x_obj, gensym("signal"));
+ outlet_new(&x->x_obj, gensym("signal"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ x->x_f = 0;
+ return (x);
+}
+
+static void sigfftw_free(t_sigfftw * x)
+{
+ fftwf_destroy_plan(x->plan);
+}
+
+static t_int *sigfftw_perform(t_int *w)
+{
+ fftwf_execute(*(fftwf_plan *)w[1]);
+
+ return (w+2);
+}
+
+static void sigfftw_dsp(t_sigfftw *x, t_signal **sp)
+{
+ int n = sp[0]->s_n;
+ float *in1 = sp[0]->s_vec;
+ float *in2 = sp[1]->s_vec;
+ float *out1 = sp[2]->s_vec;
+ float *out2 = sp[3]->s_vec;
+
+ x->dim.n=n;
+ x->dim.is=1;
+ x->dim.os=1;
+ x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL,
+ in1, in2, out1, out2,
+ FFTW_ESTIMATE);
+ dsp_add(sigfftw_perform, 1, &x->plan);
+}
+
+EXTERNAL_SETUP fftw_tilde_setup(void)
+{
+ sigfftw_class = class_new(gensym("fftw~"), sigfftw_new,
+ (t_method) sigfftw_free,
+ sizeof(t_sigfftw), 0, 0);
+ CLASS_MAINSIGNALIN(sigfftw_class, t_sigfftw, x_f);
+ class_addmethod(sigfftw_class, (t_method)sigfftw_dsp,
+ gensym("dsp"), 0);
+}
+#endif
diff --git a/fftw~.h b/fftw~.h
new file mode 100644
index 0000000..9ff9322
--- /dev/null
+++ b/fftw~.h
@@ -0,0 +1,24 @@
+#ifndef FFTW_TILDE_H_
+#define FFTW_TILDE_H_
+
+#include "fftw_config.h"
+
+#include "m_pd.h"
+
+#ifdef HAVE_LIBFFTW3F
+# include "fftw3.h"
+# include <string.h>
+#endif
+
+
+#define EXTERNAL_SETUP void
+
+static void fftw_siginvert(t_sample * s, t_int n)
+{
+ while (n!=0)
+ {
+ --n;
+ s[n]=-s[n];
+ }
+}
+#endif /* FFTW_TILDE_H_ */
diff --git a/fftw~.pd b/fftw~.pd
new file mode 100644
index 0000000..eff3051
--- /dev/null
+++ b/fftw~.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X obj 163 69 inlet~;
+#X obj 188 89 inlet~;
+#X obj 163 159 outlet~;
+#X obj 188 179 outlet~;
+#X obj 162 127 fft~;
+#X text 1 29 fall-back abstraction when there is no libFFTW installed
+;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 4 0 2 0;
+#X connect 4 1 3 0;
diff --git a/ifftw~-help.pd b/ifftw~-help.pd
new file mode 100644
index 0000000..ac9068a
--- /dev/null
+++ b/ifftw~-help.pd
@@ -0,0 +1,7 @@
+#N canvas 0 0 450 300 10;
+#X text 105 205 for help see;
+#X text 87 56 inverse complex FFT using libFFTW;
+#X obj 164 93 ifftw~;
+#X obj 213 204 ifft~;
+#X text 88 136 this object is a drop-in replacement for pd's built-in
+ifft-object;
diff --git a/ifftw~.c b/ifftw~.c
new file mode 100644
index 0000000..4818875
--- /dev/null
+++ b/ifftw~.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 1997-1999 Miller Puckette and others.
+* For information on usage and redistribution, and for a DISCLAIMER OF ALL
+* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include "fftw~.h"
+
+#ifdef HAVE_LIBFFTW3F
+/* Support for fftw3 by Tim Blechmann */
+
+/* ------------------------ ifft~ -------------------------------- */
+
+static t_class *sigifftw_class;
+
+typedef struct fftw
+{
+ t_object x_obj;
+ float x_f;
+
+ fftwf_plan plan;
+ fftwf_iodim dim;
+} t_sigifftw;
+
+static void *sigifftw_new(void)
+{
+ t_sigifftw *x = (t_sigifftw *)pd_new(sigifftw_class);
+ outlet_new(&x->x_obj, gensym("signal"));
+ outlet_new(&x->x_obj, gensym("signal"));
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ x->x_f = 0;
+ return (x);
+}
+
+static void sigifftw_free(t_sigifftw * x)
+{
+ fftwf_destroy_plan(x->plan);
+}
+
+static t_int *sigifftw_perform(t_int *w)
+{
+ fftwf_execute(*(fftwf_plan *)w[1]);
+
+ return (w+2);
+}
+
+static void sigifftw_dsp(t_sigifftw *x, t_signal **sp)
+{
+ int n = sp[0]->s_n;
+ float *in1 = sp[0]->s_vec;
+ float *in2 = sp[1]->s_vec;
+ float *out1 = sp[2]->s_vec;
+ float *out2 = sp[3]->s_vec;
+
+ x->dim.n=n;
+ x->dim.is=1;
+ x->dim.os=1;
+ x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL, in2,
+ in1, out2, out1, FFTW_ESTIMATE);
+ dsp_add(sigifftw_perform, 1, &x->plan);
+}
+
+EXTERNAL_SETUP ifftw_tilde_setup(void)
+{
+ sigifftw_class = class_new(gensym("ifftw~"), sigifftw_new,
+ (t_method) sigifftw_free,
+ sizeof(t_sigifftw), 0, 0);
+ CLASS_MAINSIGNALIN(sigifftw_class, t_sigifftw, x_f);
+ class_addmethod(sigifftw_class, (t_method)sigifftw_dsp,
+ gensym("dsp"), 0);
+}
+
+#endif
diff --git a/ifftw~.pd b/ifftw~.pd
new file mode 100644
index 0000000..0309bec
--- /dev/null
+++ b/ifftw~.pd
@@ -0,0 +1,12 @@
+#N canvas 0 0 450 300 10;
+#X obj 163 69 inlet~;
+#X obj 198 89 inlet~;
+#X obj 163 159 outlet~;
+#X obj 198 179 outlet~;
+#X obj 162 127 ifft~;
+#X text 1 29 fall-back abstraction when there is no libFFTW installed
+;
+#X connect 0 0 4 0;
+#X connect 1 0 4 1;
+#X connect 4 0 2 0;
+#X connect 4 1 3 0;
diff --git a/rfftw~-help.pd b/rfftw~-help.pd
new file mode 100644
index 0000000..0685572
--- /dev/null
+++ b/rfftw~-help.pd
@@ -0,0 +1,7 @@
+#N canvas 0 0 605 326 10;
+#X text 105 205 for help see;
+#X text 85 56 forward real FFT using libFFTW;
+#X obj 164 93 rfftw~;
+#X obj 213 204 rfft~;
+#X text 88 136 this object is a drop-in replacement for pd's built-in
+rfft-object;
diff --git a/rfftw~.c b/rfftw~.c
new file mode 100644
index 0000000..36fa923
--- /dev/null
+++ b/rfftw~.c
@@ -0,0 +1,81 @@
+/* Copyright (c) 1997-1999 Miller Puckette and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include "fftw~.h"
+
+#ifdef HAVE_LIBFFTW3F
+
+/* Support for fftw3 by Tim Blechmann */
+
+/* ----------------------- rfft~ --------------------------------- */
+
+static t_class *sigrfftw_class;
+
+typedef struct rfftw
+{
+ t_object x_obj;
+ float x_f;
+
+ fftwf_plan plan;
+ fftwf_iodim dim;
+} t_sigrfftw;
+
+static void *sigrfftw_new(void)
+{
+ t_sigrfftw *x = (t_sigrfftw *)pd_new(sigrfftw_class);
+ outlet_new(&x->x_obj, gensym("signal"));
+ outlet_new(&x->x_obj, gensym("signal"));
+ x->x_f = 0;
+ return (x);
+}
+
+static void sigrfftw_free(t_sigrfftw *x)
+{
+ fftwf_destroy_plan(x->plan);
+}
+
+static t_int *sigrfftw_perform(t_int *w)
+{
+ fftwf_execute(*(fftwf_plan*)w[1]);
+ fftw_siginvert((t_sample*)w[2],(t_int)w[3]);
+
+ return (w+4);
+}
+
+static void sigrfftw_dsp(t_sigrfftw *x, t_signal **sp)
+{
+ int n = sp[0]->s_n, n2 = (n>>1);
+ float *in = sp[0]->s_vec;
+ float *out1 = sp[1]->s_vec;
+ float *out2 = sp[2]->s_vec;
+
+ if (n < 4)
+ {
+ error("fft: minimum 4 points");
+ return;
+ }
+ else
+ {
+ x->dim.n=n;
+ x->dim.is=1;
+ x->dim.os=1;
+ x->plan = fftwf_plan_guru_split_dft_r2c(1, &(x->dim), 0, NULL,
+ in, out1, out2, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
+ dsp_add(sigrfftw_perform,3,&x->plan,out2+1,n2-1);
+ }
+
+ dsp_add_zero(out1 + n2, n2);
+ dsp_add_zero(out2 + n2, n2);
+}
+
+EXTERNAL_SETUP rfftw_tilde_setup(void)
+{
+ sigrfftw_class = class_new(gensym("rfftw~"), sigrfftw_new,
+ (t_method)sigrfftw_free,
+ sizeof(t_sigrfftw), 0, 0);
+ CLASS_MAINSIGNALIN(sigrfftw_class, t_sigrfftw, x_f);
+ class_addmethod(sigrfftw_class, (t_method)sigrfftw_dsp,
+ gensym("dsp"), 0);
+}
+#endif
diff --git a/rfftw~.pd b/rfftw~.pd
new file mode 100644
index 0000000..77bff3a
--- /dev/null
+++ b/rfftw~.pd
@@ -0,0 +1,10 @@
+#N canvas 0 0 450 300 10;
+#X obj 163 69 inlet~;
+#X obj 163 159 outlet~;
+#X obj 198 179 outlet~;
+#X obj 162 127 rfft~;
+#X text 1 29 fall-back abstraction when there is no libFFTW installed
+;
+#X connect 0 0 3 0;
+#X connect 3 0 1 0;
+#X connect 3 1 2 0;
diff --git a/rifftw~-help.pd b/rifftw~-help.pd
new file mode 100644
index 0000000..879ca5f
--- /dev/null
+++ b/rifftw~-help.pd
@@ -0,0 +1,7 @@
+#N canvas 0 0 450 300 10;
+#X text 105 205 for help see;
+#X obj 164 93 rifftw~;
+#X obj 212 204 rifft~;
+#X text 88 136 this object is a drop-in replacement for pd's built-in
+rifft-object;
+#X text 87 56 inverse real FFT using libFFTW;
diff --git a/rifftw~.c b/rifftw~.c
new file mode 100644
index 0000000..106db4e
--- /dev/null
+++ b/rifftw~.c
@@ -0,0 +1,80 @@
+/* Copyright (c) 1997-1999 Miller Puckette and others.
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
+
+#include "fftw~.h"
+
+#ifdef HAVE_LIBFFTW3F
+
+/* Support for fftw3 by Tim Blechmann */
+
+/* ----------------------- rifft~ -------------------------------- */
+
+static t_class *sigrifftw_class;
+
+typedef struct rifftw
+{
+ t_object x_obj;
+ float x_f;
+
+ fftwf_plan plan;
+ fftwf_iodim dim;
+} t_sigrifftw;
+
+static void *sigrifftw_new(void)
+{
+ t_sigrifftw *x = (t_sigrifftw *)pd_new(sigrifftw_class);
+ inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+ outlet_new(&x->x_obj, gensym("signal"));
+ x->x_f = 0;
+ return (x);
+}
+
+static void sigrifftw_free(t_sigrifftw *x)
+{
+ fftwf_destroy_plan(x->plan);
+}
+
+static t_int *sigrifftw_perform(t_int *w)
+{
+ fftw_siginvert((t_sample *)w[2],w[3]);
+ fftwf_execute(*(fftwf_plan*)w[1]);
+
+ return (w+4);
+}
+
+static void sigrifftw_dsp(t_sigrifftw *x, t_signal **sp)
+{
+ int n = sp[0]->s_n, n2 = (n>>1);
+ float *in1 = sp[0]->s_vec;
+ float *in2 = sp[1]->s_vec;
+ float *out = sp[2]->s_vec;
+
+ if (n < 4)
+ {
+ error("fft: minimum 4 points");
+ return;
+ }
+
+ else
+ {
+ x->dim.n=n;
+ x->dim.is=1;
+ x->dim.os=1;
+ x->plan = fftwf_plan_guru_split_dft_c2r(1, &(x->dim), 0, NULL,
+ in1, in2, out, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT);
+ dsp_add_zero(in1+ n/2, n/2);
+ dsp_add(sigrifftw_perform,3,&x->plan,in2,n2);
+ }
+}
+
+EXTERNAL_SETUP rifftw_tilde_setup(void)
+{
+ sigrifftw_class = class_new(gensym("rifftw~"), sigrifftw_new,
+ (t_method)sigrifftw_free,
+ sizeof(t_sigrifftw), 0, 0);
+ CLASS_MAINSIGNALIN(sigrifftw_class, t_sigrifftw, x_f);
+ class_addmethod(sigrifftw_class, (t_method)sigrifftw_dsp,
+ gensym("dsp"), 0);
+}
+#endif
diff --git a/rifftw~.pd b/rifftw~.pd
new file mode 100644
index 0000000..1b99abd
--- /dev/null
+++ b/rifftw~.pd
@@ -0,0 +1,10 @@
+#N canvas 0 0 450 300 10;
+#X obj 163 69 inlet~;
+#X obj 163 159 outlet~;
+#X obj 162 127 rifft~;
+#X obj 206 99 inlet~;
+#X text 1 29 fall-back abstraction when there is no libFFTW installed
+;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
+#X connect 3 0 2 1;