Skip to content
Snippets Groups Projects
Commit b9d6f6cd authored by Ivica Bukvic's avatar Ivica Bukvic
Browse files

improved fftw3 support

parent 5302598f
No related branches found
No related tags found
No related merge requests found
...@@ -47,8 +47,10 @@ AC_ARG_ENABLE(setuid, [ --enable-setuid install as setuid (linux)], ...@@ -47,8 +47,10 @@ AC_ARG_ENABLE(setuid, [ --enable-setuid install as setuid (linux)],
setuid=$enableval) setuid=$enableval)
AC_ARG_ENABLE(fftw, [ --enable-fftw use FFTW package], AC_ARG_ENABLE(fftw, [ --enable-fftw use FFTW package],
fftw=$enableval) fftw=$enableval)
AC_ARG_ENABLE(fat, [ --disable-fat build fat binary on Mac OS X], AC_ARG_ENABLE(fat, [ --disable-fat build fat binary on Mac OS X],
fat=$enableval, fat="yes") fat=$enableval, fat="yes")
AC_ARG_ENABLE(tk, [ --disable-tk build without tcl/tk-GUI],
tk=$enableval)
dnl Checks for programs. dnl Checks for programs.
AC_PROG_CC AC_PROG_CC
...@@ -96,8 +98,8 @@ AC_CHECK_LIB(pthread, pthread_create,PDLIB="$PDLIB -lpthread", ...@@ -96,8 +98,8 @@ AC_CHECK_LIB(pthread, pthread_create,PDLIB="$PDLIB -lpthread",
dnl Check for fftw package dnl Check for fftw package
if test x$fftw = "xyes"; if test x$fftw = "xyes";
then then
AC_CHECK_LIB(fftw, fftw_one,PDLIB="$PDLIB -lfftw", AC_CHECK_LIB(fftw3f, fftwf_version,PDLIB="$PDLIB -lfftw3f",
echo "fftw package not found - using built-in FFT"; fftw=no) echo "fftw3 package not found - using built-in FFT"; fftw=no)
fi fi
dnl look for tcl 8.x... do I really have to go through all this!? dnl look for tcl 8.x... do I really have to go through all this!?
...@@ -176,13 +178,10 @@ else ...@@ -176,13 +178,10 @@ else
GUISRC= GUISRC=
fi fi
# leave the executable as 'pd' on Mac OS X and Windows, but call it PDEXEC=pd-l2ork
# 'pdl2ork' on GNU/Linux
PDEXEC=pd
if test `uname -s` = Linux; if test `uname -s` = Linux -o `uname -s` = "GNU/kFreeBSD" -o `uname -s` = "GNU";
then then
PDEXEC=pd-l2ork
dnl Ckecking for ALSA dnl Ckecking for ALSA
echo .................... alsa= $alsa echo .................... alsa= $alsa
dnl This should be fixed so Pd can use ALSA shared libraries where appropriate. dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
...@@ -206,7 +205,16 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate. ...@@ -206,7 +205,16 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
CPPFLAGS="-DDL_OPEN -DPA_USE_OSS -DUNIX -DUNISTD\ CPPFLAGS="-DDL_OPEN -DPA_USE_OSS -DUNIX -DUNISTD\
-DUSEAPI_OSS \ -DUSEAPI_OSS \
-fno-strict-aliasing" -fno-strict-aliasing"
SYSSRC="s_midi_oss.c s_audio_oss.c" dnl No OSS on hurd
if test `uname -s` = "GNU";
then
SYSSRC="s_midi_dummy.c"
else
SYSSRC="s_midi_oss.c s_audio_oss.c"
CPPFLAGS=$CPPFLAGS" -DPA_USE_OSS -DUSEAPI_OSS"
fi
if test x$alsa = "xyes"; if test x$alsa = "xyes";
then then
SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c" SYSSRC=$SYSSRC" s_audio_alsa.c s_audio_alsamm.c s_midi_alsa.c"
...@@ -223,7 +231,6 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate. ...@@ -223,7 +231,6 @@ dnl This should be fixed so Pd can use ALSA shared libraries where appropriate.
-I../portmidi/pm_common \ -I../portmidi/pm_common \
-I../portmidi/pm_linux" -I../portmidi/pm_linux"
SYSSRC="s_audio_pa.c \ SYSSRC="s_audio_pa.c \
s_audio_pablio.c \
s_audio_paring.c \ s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \ ../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \ ../portaudio/src/common/pa_converters.c \
...@@ -281,7 +288,7 @@ then ...@@ -281,7 +288,7 @@ then
-framework AudioUnit -framework AudioToolbox \ -framework AudioUnit -framework AudioToolbox \
-framework Carbon -framework CoreMIDI" -framework Carbon -framework CoreMIDI"
EXT=pd_darwin EXT=pd_darwin
CPPFLAGS="-DDL_OPEN -DMACOSX -DUNISTD -I/usr/X11R6/include \ CPPFLAGS="-DHAVE_LIBDL -DMACOSX -DHAVE_UNISTD_H -I/usr/X11R6/include \
-I../portaudio/include -I../portaudio/src/common \ -I../portaudio/include -I../portaudio/src/common \
-I../portaudio/src/os/mac_osx/ \ -I../portaudio/src/os/mac_osx/ \
-I../portmidi/pm_common -I../portmidi/pm_mac \ -I../portmidi/pm_common -I../portmidi/pm_mac \
...@@ -303,7 +310,6 @@ then ...@@ -303,7 +310,6 @@ then
EXTERNTARGET=d_ppc EXTERNTARGET=d_ppc
fi fi
SYSSRC="s_midi_pm.c s_audio_pa.c \ SYSSRC="s_midi_pm.c s_audio_pa.c \
s_audio_pablio.c \
s_audio_paring.c \ s_audio_paring.c \
../portaudio/src/common/pa_allocation.c \ ../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \ ../portaudio/src/common/pa_converters.c \
...@@ -323,8 +329,6 @@ then ...@@ -323,8 +329,6 @@ then
../portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c \ ../portaudio/src/hostapi/coreaudio/pa_mac_core_utilities.c \
../portmidi/pm_mac/pmmac.c \ ../portmidi/pm_mac/pmmac.c \
../portmidi/pm_mac/pmmacosxcm.c \ ../portmidi/pm_mac/pmmacosxcm.c \
../portmidi/pm_mac/finddefault.c \
../portmidi/pm_mac/readbinaryplist.c \
../portmidi/pm_common/pmutil.c \ ../portmidi/pm_common/pmutil.c \
../portmidi/pm_common/portmidi.c \ ../portmidi/pm_common/portmidi.c \
../portmidi/porttime/ptmacosx_cf.c " ../portmidi/porttime/ptmacosx_cf.c "
...@@ -357,7 +361,7 @@ then ...@@ -357,7 +361,7 @@ then
OSNUMBER=2 OSNUMBER=2
if test x$jack = "xyes"; if test x$jack = "xyes";
then then
LDFLAGS=$LDFLAGS" -weak_framework Jackmp" LDFLAGS=$LDFLAGS" -weak_framework Jackmp"
fi fi
if test x$jack = "xrun"; if test x$jack = "xrun";
then then
...@@ -377,7 +381,7 @@ then ...@@ -377,7 +381,7 @@ then
-mwindows -mms-bitfields "$MORECFLAGS -mwindows -mms-bitfields "$MORECFLAGS
PDLIB=$PDLIB" -lwsock32 -lwinmm -lole32 -lstdc++" PDLIB=$PDLIB" -lwsock32 -lwinmm -lole32 -lstdc++"
SYSSRC="s_audio_pa.c s_audio_pablio.c s_audio_paring.c \ SYSSRC="s_audio_pa.c s_audio_paring.c \
s_audio_mmio.c s_midi_mmio.c \ s_audio_mmio.c s_midi_mmio.c \
../portaudio/src/common/pa_allocation.c \ ../portaudio/src/common/pa_allocation.c \
../portaudio/src/common/pa_converters.c \ ../portaudio/src/common/pa_converters.c \
...@@ -418,7 +422,7 @@ fi ...@@ -418,7 +422,7 @@ fi
if test x$fftw = "xyes"; if test x$fftw = "xyes";
then then
SYSSRC=$SYSSRC" d_fft_fftw.c d_fftroutine.c" SYSSRC=$SYSSRC" d_fft_fftw.c d_fftroutine.c"
LDFLAGS=$LDFLAGS" -lfftw" LDFLAGS=$LDFLAGS" -lfftw3"
else else
SYSSRC=$SYSSRC" d_fft_mayer.c d_fftroutine.c" SYSSRC=$SYSSRC" d_fft_mayer.c d_fftroutine.c"
fi fi
......
...@@ -4,31 +4,32 @@ ...@@ -4,31 +4,32 @@
/* --------- Pd interface to FFTW library; imitate Mayer API ---------- */ /* --------- Pd interface to FFTW library; imitate Mayer API ---------- */
#include "m_pd.h" /* changes and additions for FFTW3 by Thomas Grill */
#ifdef MSW
#include <malloc.h>
#else
#include <alloca.h>
#endif
#error oops -- I'm talking to the old fftw. Apparently it's still changing.
#include <fftw.h> #include "m_pd.h"
#include <fftw3.h>
int ilog2(int n); int ilog2(int n);
#define MINFFT 5 #define MINFFT 0
#define MAXFFT 30 #define MAXFFT 30
/* from the FFTW website: /* from the FFTW website:
fftw_complex in[N], out[N]; #include <fftw3.h>
...
{
fftw_complex *in, *out;
fftw_plan p; fftw_plan p;
... ...
p = fftw_create_plan(N, FFTW_FORWARD, FFTW_ESTIMATE); in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * N);
p = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
... ...
fftw_one(p, in, out); fftw_execute(p);
... ...
fftw_destroy_plan(p); fftw_destroy_plan(p);
fftw_free(in); fftw_free(out);
}
FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you FFTW_FORWARD or FFTW_BACKWARD, and indicates the direction of the transform you
are interested in. Alternatively, you can use the sign of the exponent in the are interested in. Alternatively, you can use the sign of the exponent in the
...@@ -37,57 +38,126 @@ respectively. The flags argument is either FFTW_MEASURE ...@@ -37,57 +38,126 @@ respectively. The flags argument is either FFTW_MEASURE
*/ */
static fftw_plan fftw_pvec[2 * (MAXFFT+1 - MINFFT)]; /* complex stuff */
typedef struct {
fftwf_plan plan;
fftwf_complex *in,*out;
} cfftw_info;
static cfftw_info cfftw_fwd[MAXFFT+1 - MINFFT],cfftw_bwd[MAXFFT+1 - MINFFT];
static cfftw_info *cfftw_getplan(int n,int fwd)
{
cfftw_info *info;
int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT)
return (0);
info = (fwd?cfftw_fwd:cfftw_bwd)+(logn-MINFFT);
if (!info->plan)
{
info->in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * n);
info->plan = fftwf_plan_dft_1d(n, info->in, info->out, fwd?FFTW_FORWARD:FFTW_BACKWARD, FFTW_MEASURE);
}
return info;
}
static fftw_plan fftw_getplan(int n, int dir) /* real stuff */
typedef struct {
fftwf_plan plan;
float *in,*out;
} rfftw_info;
static rfftw_info rfftw_fwd[MAXFFT+1 - MINFFT],rfftw_bwd[MAXFFT+1 - MINFFT];
static rfftw_info *rfftw_getplan(int n,int fwd)
{ {
logn = ilog2(n); rfftw_info *info;
int logn = ilog2(n);
if (logn < MINFFT || logn > MAXFFT) if (logn < MINFFT || logn > MAXFFT)
return (0); return (0);
int indx = 2*(logn-MINFFT) + inverse); info = (fwd?rfftw_fwd:rfftw_bwd)+(logn-MINFFT);
if (!fftw_pvec[indx] if (!info->plan)
fftw_pvec[indx] = fftw_create_plan(N, dir, FFTW_MEASURE); {
return (fftw_pvec[indx]); info->in = (float*) fftwf_malloc(sizeof(float) * n);
info->out = (float*) fftwf_malloc(sizeof(float) * n);
info->plan = fftwf_plan_r2r_1d(n, info->in, info->out, fwd?FFTW_R2HC:FFTW_HC2R, FFTW_MEASURE);
}
return info;
} }
EXTERN void mayer_fht(float *fz, int n) EXTERN void mayer_fht(float *fz, int n)
{ {
post("FHT: not yet implemented"); post("FHT: not yet implemented");
} }
static void mayer_dofft(int n, float *fz1, float *fz2, int dir) static void mayer_do_cfft(int n, float *fz1, float *fz2, int fwd)
{ {
float *inbuf, *outbuf, *fp1, *fp2, *fp3;
int i; int i;
fftw_plan p = fftw_getplan(n, dir); float *fz;
inbuf = alloca(n * (4 * sizeof(float))); cfftw_info *p = cfftw_getplan(n, fwd);
outbuf = inbuf + 2*n;
if (!p) if (!p)
return; return;
for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = inbuf; i < n; i++)
fp3[0] = *fp1++, fp3[1] = *fp2++, fp3 += 2; for (i = 0, fz = (float *)p->in; i < n; i++)
fftw_one(p, inbuf, outbuf); fz[i*2] = fz1[i], fz[i*2+1] = fz2[i];
for (i = 0, fp1 = fz1, fp2 = fz2, fp3 = outbuf; i < n; i++)
*fp1++ = fp3[0], *fp2++ = fp3[1], fp3 += 2; fftwf_execute(p->plan);
for (i = 0, fz = (float *)p->out; i < n; i++)
fz1[i] = fz[i*2], fz2[i] = fz[i*2+1];
} }
EXTERN void mayer_fft(int n, float *fz1, float *fz2) EXTERN void mayer_fft(int n, float *fz1, float *fz2)
{ {
mayer_dofft(n, fz1, fz2, FFTW_FORWARD); mayer_do_cfft(n, fz1, fz2, 1);
} }
EXTERN void mayer_ifft(int n, float *fz1, float *fz2) EXTERN void mayer_ifft(int n, float *fz1, float *fz2)
{ {
mayer_dofft(n, fz1, fz2, FFTW_BACKWARD); mayer_do_cfft(n, fz1, fz2, 0);
} }
/*
in the following the sign flips are done to
be compatible with the mayer_fft implementation,
but it's probably the mayer_fft that should be corrected...
*/
EXTERN void mayer_realfft(int n, float *fz) EXTERN void mayer_realfft(int n, float *fz)
{ {
post("rfft: not yet implemented"); int i;
rfftw_info *p = rfftw_getplan(n, 1);
if (!p)
return;
for (i = 0; i < n; i++)
p->in[i] = fz[i];
fftwf_execute(p->plan);
for (i = 0; i < n/2+1; i++)
fz[i] = p->out[i];
for (; i < n; i++)
fz[i] = -p->out[i];
} }
EXTERN void mayer_realifft(int n, float *fz) EXTERN void mayer_realifft(int n, float *fz)
{ {
post("rifft: not yet implemented"); int i;
rfftw_info *p = rfftw_getplan(n, 0);
if (!p)
return;
for (i = 0; i < n/2+1; i++)
p->in[i] = fz[i];
for (; i < n; i++)
p->in[i] = -fz[i];
fftwf_execute(p->plan);
for (i = 0; i < n; i++)
fz[i] = p->out[i];
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment