From 6c61b72cc7be59138b59b1d64b64377fc5c54395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?IOhannes=20m=20zm=C3=B6lnig?= Date: Wed, 20 Sep 2006 11:22:29 +0000 Subject: library providing FFT-objects using the (fast!) libFFTW svn path=/trunk/externals/fftw/; revision=5978 --- LICENSE.txt | 30 ++++++++ Makefile | 3 + Makefile.in | 97 ++++++++++++++++++++++++ README.txt | 31 ++++++++ configure.ac | 220 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fftw_config.h | 2 + fftw_config.h.in | 1 + fftw~-help.pd | 7 ++ fftw~.c | 71 ++++++++++++++++++ fftw~.h | 24 ++++++ fftw~.pd | 12 +++ ifftw~-help.pd | 7 ++ ifftw~.c | 71 ++++++++++++++++++ ifftw~.pd | 12 +++ rfftw~-help.pd | 7 ++ rfftw~.c | 81 ++++++++++++++++++++ rfftw~.pd | 10 +++ rifftw~-help.pd | 7 ++ rifftw~.c | 80 ++++++++++++++++++++ rifftw~.pd | 10 +++ 20 files changed, 783 insertions(+) create mode 100644 LICENSE.txt create mode 100644 Makefile create mode 100644 Makefile.in create mode 100644 README.txt create mode 100644 configure.ac create mode 100644 fftw_config.h create mode 100644 fftw_config.h.in create mode 100644 fftw~-help.pd create mode 100644 fftw~.c create mode 100644 fftw~.h create mode 100644 fftw~.pd create mode 100644 ifftw~-help.pd create mode 100644 ifftw~.c create mode 100644 ifftw~.pd create mode 100644 rfftw~-help.pd create mode 100644 rfftw~.c create mode 100644 rfftw~.pd create mode 100644 rifftw~-help.pd create mode 100644 rifftw~.c create mode 100644 rifftw~.pd 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= enforce a certain pd-version (e.g. 0.37)]) +AC_ARG_WITH(extension, [ --with-extension= 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 +#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 +#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; -- cgit v1.2.1