add support for ooura so that aubio can be build without fftw
authorPaul Brossier <piem@piem.org>
Thu, 17 Nov 2011 01:29:35 +0000 (17:29 -0800)
committerPaul Brossier <piem@piem.org>
Thu, 17 Nov 2011 01:29:35 +0000 (17:29 -0800)
configure.ac
src/Makefile.am
src/mathutils.c
src/spectral/fft.c
src/wscript_build
wscript

index 037b27d5b1e4ffac9c0b282c119992a23c9bd19c..052bfd60c46ee11472676e0a41ac598612d89bae 100644 (file)
@@ -173,27 +173,38 @@ fi
 
 dnl Check for fftw3 (required)
 dnl if we compile in double precsion, default to fftw3, else fftw3f
+
+AC_ARG_ENABLE(fftw3,
+  AC_HELP_STRING([--enable-fftw3],[compile with fftw3 [[default=auto]]]),
+  [with_fftw3=$enableval],
+  with_fftw3="yes")
+
 if test "$with_double_precision" = "yes"; then
     default_fftw3f="no"
 else
-    default_fftw3f="yes"
+    default_fftw3f=$with_fftw3
 fi
+
 AC_ARG_ENABLE(fftw3f,
   AC_HELP_STRING([--enable-fftw3f],[compile with fftw3f [[default=auto]]]),
   [with_fftw3f=$enableval],
   [with_fftw3f=$default_fftw3f])
+
+# check if we have fftw3f
 if test "$with_fftw3f" = "yes"; then
   PKG_CHECK_MODULES(FFTWLIB,    fftw3f >= 3.0.0,     HAVE_FFTW3F=1, HAVE_FFTW3F=0)
 else
-  PKG_CHECK_MODULES(FFTWLIB,    fftw3  >= 3.0.0,     HAVE_FFTW3=1)
+# check if we have fftw3
+if test "$with_fftw3" = "yes"; then
+  PKG_CHECK_MODULES(FFTWLIB,    fftw3  >= 3.0.0,     HAVE_FFTW3=1, HAVE_FFTW3=0)
 fi
-if test "${HAVE_FFTW3F}" = "0"; then
-  PKG_CHECK_MODULES(FFTWLIB,    fftw3  >= 3.0.0,     HAVE_FFTW3=1)
 fi
+
 if test "${HAVE_FFTW3}" = "1"; then
   AC_DEFINE(HAVE_FFTW3,1,[Define to enable fftw3 support])
 fi
 if test "${HAVE_FFTW3F}" = "1"; then
+  AC_DEFINE(HAVE_FFTW3,1,[Define to enable fftw3 support])
   AC_DEFINE(HAVE_FFTW3F,1,[Define to enable fftw3f support])
 fi
 
@@ -263,12 +274,12 @@ echo
 echo "**************************************************************"
 echo "Summary:"
 if test "${HAVE_FFTW3F}" = "1"; then
-  echo "Fftw3:                   yes (using fftw3f)"
+  echo "FFT:                     using fftw3f"
 else
 if test "${HAVE_FFTW3}" = "1"; then
-  echo "Fftw3:                   yes (not using fftw3f)"
+  echo "Fft:                     using fftw3"
 else
-  echo "Fftw3:                   no (that should not happen)"
+  echo "Fft:                     using ooura"
 fi
 fi
 if test "${HAVE_SNDFILE}" = "1"; then
index ba91c2470fbcbf1a9aa42a807c3f8876456a32f9..f088d934ac512e0464d913f471fe907c5125e23a 100644 (file)
@@ -58,6 +58,7 @@ libaubio_la_SOURCES = \
        spectral/mfcc.c \
        spectral/phasevoc.c \
        spectral/fft.c \
+       spectral/ooura_fft8g.c \
        spectral/tss.c \
        spectral/specdesc.c \
        spectral/statistics.c \
index a1eb2cef992f5f6cadff7c8a2cba31bdfb3dfeb1..0c764552488fcd954f9b2e04822cd8f00d1ff89d 100644 (file)
@@ -511,11 +511,11 @@ aubio_autocorr (fvec_t * input, fvec_t * output)
 void
 aubio_cleanup (void)
 {
-#if HAVE_FFTW3
-  fftw_cleanup ();
-#else
-#if HAVE_FFTW3F
+#ifdef HAVE_FFTW3F
   fftwf_cleanup ();
+#else
+#ifdef HAVE_FFTW3
+  fftw_cleanup ();
 #endif
 #endif
 }
index 10bcaad35ba59c815412fab18b9939197fb4dfc7..f7dafe067bba9532b4d725449b81017f50403db4 100644 (file)
 #include "mathutils.h"
 #include "spectral/fft.h"
 
+#ifdef HAVE_FFTW3
 /* note that <complex.h> is not included here but only in aubio_priv.h, so that
  * c++ projects can still use their own complex definition. */
 #include <fftw3.h>
 #include <pthread.h>
 
 #ifdef HAVE_COMPLEX_H
-#if HAVE_FFTW3F
+#ifdef HAVE_FFTW3F
 /** fft data type with complex.h and fftw3f */
 #define FFTW_TYPE fftwf_complex
 #else
@@ -38,7 +39,7 @@
 #define FFTW_TYPE fftw_complex
 #endif
 #else
-#if HAVE_FFTW3F
+#ifdef HAVE_FFTW3F
 /** fft data type without complex.h and with fftw3f */
 #define FFTW_TYPE float
 #else
@@ -50,7 +51,7 @@
 /** fft data type */
 typedef FFTW_TYPE fft_data_t;
 
-#if HAVE_FFTW3F
+#ifdef HAVE_FFTW3F
 #define fftw_malloc            fftwf_malloc
 #define fftw_free              fftwf_free
 #define fftw_execute           fftwf_execute
@@ -61,13 +62,13 @@ typedef FFTW_TYPE fft_data_t;
 #define fftw_destroy_plan      fftwf_destroy_plan
 #endif
 
-#if HAVE_FFTW3F
-#if HAVE_AUBIO_DOUBLE
+#ifdef HAVE_FFTW3F
+#ifdef HAVE_AUBIO_DOUBLE
 #warning "Using aubio in double precision with fftw3 in single precision"
 #endif /* HAVE_AUBIO_DOUBLE */
 #define real_t float 
 #else /* HAVE_FFTW3F */
-#if !HAVE_AUBIO_DOUBLE
+#ifndef HAVE_AUBIO_DOUBLE
 #warning "Using aubio in single precision with fftw3 in double precision"
 #endif /* HAVE_AUBIO_DOUBLE */
 #define real_t double 
@@ -76,18 +77,32 @@ typedef FFTW_TYPE fft_data_t;
 // a global mutex for FFTW thread safety
 pthread_mutex_t aubio_fftw_mutex = PTHREAD_MUTEX_INITIALIZER;
 
+#endif /* HAVE_FFTW3 */
+
 struct _aubio_fft_t {
   uint_t winsize;
   uint_t fft_size;
+#ifdef HAVE_FFTW3
   real_t *in, *out;
   fftw_plan pfw, pbw;
   fft_data_t * specdata;     /* complex spectral data */
+#else
+  double *in, *out;
+  double *w;
+  int *ip;
+#endif /* HAVE_FFTW3 */
   fvec_t * compspec;
 };
 
-aubio_fft_t * new_aubio_fft(uint_t winsize) {
+#ifndef HAVE_FFTW3
+// let's use ooura instead
+extern void rdft(int, int, double *, int *, double *);
+#endif
+
+aubio_fft_t * new_aubio_fft (uint_t winsize) {
   aubio_fft_t * s = AUBIO_NEW(aubio_fft_t);
   uint_t i;
+#ifdef HAVE_FFTW3
   s->winsize  = winsize;
   /* allocate memory */
   s->in       = AUBIO_ARRAY(real_t,winsize);
@@ -114,17 +129,32 @@ aubio_fft_t * new_aubio_fft(uint_t winsize) {
   for (i = 0; i < s->fft_size; i++) {
     s->specdata[i] = 0.;
   }
+#else
+  s->winsize = winsize;
+  s->fft_size = winsize / 2 + 1;
+  s->compspec = new_fvec(winsize);
+  s->in    = AUBIO_ARRAY(double, s->fft_size);
+  s->out   = AUBIO_ARRAY(double, s->fft_size);
+  s->ip    = AUBIO_ARRAY(int   , s->fft_size);
+  s->w     = AUBIO_ARRAY(double, s->fft_size);
+  s->ip[0] = 0;
+#endif
   return s;
 }
 
 void del_aubio_fft(aubio_fft_t * s) {
   /* destroy data */
   del_fvec(s->compspec);
+#ifdef HAVE_FFTW3
   fftw_destroy_plan(s->pfw);
   fftw_destroy_plan(s->pbw);
   fftw_free(s->specdata);
+#else /* HAVE_FFTW3 */
+  AUBIO_FREE(s->w);
+  AUBIO_FREE(s->ip);
+#endif /* HAVE_FFTW3 */
   AUBIO_FREE(s->out);
-  AUBIO_FREE(s->in );
+  AUBIO_FREE(s->in);
   AUBIO_FREE(s);
 }
 
@@ -139,44 +169,68 @@ void aubio_fft_rdo(aubio_fft_t * s, cvec_t * spectrum, fvec_t * output) {
 }
 
 void aubio_fft_do_complex(aubio_fft_t * s, fvec_t * input, fvec_t * compspec) {
-  uint_t j;
-  for (j=0; j < s->winsize; j++) {
-    s->in[j] = input->data[j];
+  uint_t i;
+  for (i=0; i < s->winsize; i++) {
+    s->in[i] = input->data[i];
   }
+#ifdef HAVE_FFTW3
   fftw_execute(s->pfw);
 #ifdef HAVE_COMPLEX_H
   compspec->data[0] = REAL(s->specdata[0]);
-  for (j = 1; j < s->fft_size -1 ; j++) {
-    compspec->data[j] = REAL(s->specdata[j]);
-    compspec->data[compspec->length - j] = IMAG(s->specdata[j]);
+  for (i = 1; i < s->fft_size -1 ; i++) {
+    compspec->data[i] = REAL(s->specdata[i]);
+    compspec->data[compspec->length - i] = IMAG(s->specdata[i]);
   }
   compspec->data[s->fft_size-1] = REAL(s->specdata[s->fft_size-1]);
-#else
-  for (j = 0; j < s->fft_size; j++) {
-    compspec->data[j] = s->specdata[j];
+#else /* HAVE_COMPLEX_H  */
+  for (i = 0; i < s->fft_size; i++) {
+    compspec->data[i] = s->specdata[i];
   }
-#endif
+#endif /* HAVE_COMPLEX_H */
+#else /* HAVE_FFTW3 */
+  rdft(s->winsize, 1, s->in, s->ip, s->w);
+  compspec->data[0] = s->in[0];
+  compspec->data[s->winsize / 2] = s->in[1];
+  for (i = 1; i < s->fft_size - 1; i++) {
+    compspec->data[i] = s->in[2 * i];
+    compspec->data[s->winsize - i] = - s->in[2 * i + 1];
+  }
+#endif /* HAVE_FFTW3 */
 }
 
 void aubio_fft_rdo_complex(aubio_fft_t * s, fvec_t * compspec, fvec_t * output) {
-  uint_t j;
+  uint_t i;
+#ifdef HAVE_FFTW3
   const smpl_t renorm = 1./(smpl_t)s->winsize;
 #ifdef HAVE_COMPLEX_H
   s->specdata[0] = compspec->data[0];
-  for (j=1; j < s->fft_size - 1; j++) {
-    s->specdata[j] = compspec->data[j] + 
-      I * compspec->data[compspec->length - j];
+  for (i=1; i < s->fft_size - 1; i++) {
+    s->specdata[i] = compspec->data[i] +
+      I * compspec->data[compspec->length - i];
   }
   s->specdata[s->fft_size - 1] = compspec->data[s->fft_size - 1];
 #else
-  for (j=0; j < s->fft_size; j++) {
-    s->specdata[j] = compspec->data[j];
+  for (i=0; i < s->fft_size; i++) {
+    s->specdata[i] = compspec->data[i];
   }
 #endif
   fftw_execute(s->pbw);
-  for (j = 0; j < output->length; j++) {
-    output->data[j] = s->out[j]*renorm;
+  for (i = 0; i < output->length; i++) {
+    output->data[i] = s->out[i]*renorm;
+  }
+#else /* HAVE_FFTW3 */
+  smpl_t scale = 2.0 / s->winsize;
+  s->out[0] = compspec->data[0];
+  s->out[1] = compspec->data[s->winsize / 2];
+  for (i = 1; i < s->fft_size - 1; i++) {
+    s->out[2 * i] = compspec->data[i];
+    s->out[2 * i + 1] = - compspec->data[s->winsize - i];
   }
+  rdft(s->winsize, -1, s->out, s->ip, s->w);
+  for (i=0; i < s->winsize; i++) {
+    output->data[i] = s->out[i] * scale;
+  }
+#endif /* HAVE_FFTW3 */
 }
 
 void aubio_fft_get_spectrum(fvec_t * compspec, cvec_t * spectrum) {
@@ -190,15 +244,15 @@ void aubio_fft_get_realimag(cvec_t * spectrum, fvec_t * compspec) {
 }
 
 void aubio_fft_get_phas(fvec_t * compspec, cvec_t * spectrum) {
-  uint_t j;
+  uint_t i;
   if (compspec->data[0] < 0) {
     spectrum->phas[0] = PI;
   } else {
     spectrum->phas[0] = 0.;
   }
-  for (j=1; j < spectrum->length - 1; j++) {
-    spectrum->phas[j] = ATAN2(compspec->data[compspec->length-j],
-        compspec->data[j]);
+  for (i=1; i < spectrum->length - 1; i++) {
+    spectrum->phas[i] = ATAN2(compspec->data[compspec->length-i],
+        compspec->data[i]);
   }
   if (compspec->data[compspec->length/2] < 0) {
     spectrum->phas[spectrum->length - 1] = PI;
@@ -208,28 +262,28 @@ void aubio_fft_get_phas(fvec_t * compspec, cvec_t * spectrum) {
 }
 
 void aubio_fft_get_norm(fvec_t * compspec, cvec_t * spectrum) {
-  uint_t j = 0;
+  uint_t i = 0;
   spectrum->norm[0] = ABS(compspec->data[0]);
-  for (j=1; j < spectrum->length - 1; j++) {
-    spectrum->norm[j] = SQRT(SQR(compspec->data[j]) 
-        + SQR(compspec->data[compspec->length - j]) );
+  for (i=1; i < spectrum->length - 1; i++) {
+    spectrum->norm[i] = SQRT(SQR(compspec->data[i])
+        + SQR(compspec->data[compspec->length - i]) );
   }
-  spectrum->norm[spectrum->length-1] = 
+  spectrum->norm[spectrum->length-1] =
     ABS(compspec->data[compspec->length/2]);
 }
 
 void aubio_fft_get_imag(cvec_t * spectrum, fvec_t * compspec) {
-  uint_t j;
-  for (j = 1; j < ( compspec->length + 1 ) / 2 /*- 1 + 1*/; j++) {
-    compspec->data[compspec->length - j] =
-      spectrum->norm[j]*SIN(spectrum->phas[j]);
+  uint_t i;
+  for (i = 1; i < ( compspec->length + 1 ) / 2 /*- 1 + 1*/; i++) {
+    compspec->data[compspec->length - i] =
+      spectrum->norm[i]*SIN(spectrum->phas[i]);
   }
 }
 
 void aubio_fft_get_real(cvec_t * spectrum, fvec_t * compspec) {
-  uint_t j;
-  for (j = 0; j < compspec->length / 2 + 1; j++) {
-    compspec->data[j] = 
-      spectrum->norm[j]*COS(spectrum->phas[j]);
+  uint_t i;
+  for (i = 0; i < compspec->length / 2 + 1; i++) {
+    compspec->data[i] = 
+      spectrum->norm[i]*COS(spectrum->phas[i]);
   }
 }
index 792c81b1f4512626bee87e9bb2cf151c66cd74f9..eb1336b3df713e4dd22d44ba78003c6ce1c26a45 100644 (file)
@@ -1,10 +1,17 @@
+uselib = ['SAMPLERATE']
+if 'HAVE_FFTW3' in conf.get_env():
+  source = bld.path.ant_glob('*.c **/*.c', excl = ['**/ooura_fft8g.c'])
+  uselib += ['FFTW3', 'FFTW3F']
+else:
+  source = bld.path.ant_glob('*.c **/*.c')
+
 # build libaubio
-libaubio = bld.new_task_gen(
-    features = 'c cshlib',
+bld.shlib(
     includes = ['.'],
-    source = bld.path.ant_glob('*.c **/*.c'),
+    source = source,
     target = 'aubio',
-    uselib = ['FFTW3', 'FFTW3F', 'SAMPLERATE'],
+    lib = 'm',
+    uselib = uselib,
     vnum = bld.env['LIB_VERSION'])
 
 # install headers, except _priv.h ones
diff --git a/wscript b/wscript
index bd8ea00e79a271229a742ccc77df1af8bd3a015a..884dc6f057edccfc2142cfdf6e238042488026cf 100644 (file)
--- a/wscript
+++ b/wscript
@@ -30,6 +30,8 @@ def init(opt):
 def options(opt):
   opt.add_option('--enable-double', action='store_true', default=False,
       help='compile aubio in double precision mode')
+  opt.add_option('--disable-fftw', action='store_true', default=False,
+      help='compile with ooura instead of fftw')
   opt.add_option('--disable-fftw3f', action='store_true', default=False,
       help='compile with fftw3 instead of fftw3f')
   opt.add_option('--enable-complex', action='store_true', default=False,
@@ -85,18 +87,23 @@ def configure(conf):
   else:
     conf.define('HAVE_AUBIO_DOUBLE', 0)
 
-  # one of fftwf or fftw3f
-  if (Options.options.disable_fftw3f == True):
-    conf.check_cfg(package = 'fftw3', atleast_version = '3.0.0',
-        args = '--cflags --libs')
-  else:
-    # fftw3f not disabled, take most sensible one according to enable_double
-    if (Options.options.enable_double == True):
+  if (Options.options.disable_fftw == False):
+    # one of fftwf or fftw3f
+    if (Options.options.disable_fftw3f == True):
       conf.check_cfg(package = 'fftw3', atleast_version = '3.0.0',
           args = '--cflags --libs')
     else:
-      conf.check_cfg(package = 'fftw3f', atleast_version = '3.0.0',
-          args = '--cflags --libs')
+      # fftw3f not disabled, take most sensible one according to enable_double
+      if (Options.options.enable_double == True):
+        conf.check_cfg(package = 'fftw3', atleast_version = '3.0.0',
+            args = '--cflags --libs')
+      else:
+        conf.check_cfg(package = 'fftw3f', atleast_version = '3.0.0',
+            args = '--cflags --libs')
+    conf.define('HAVE_FFTW3', 1)
+  else:
+    # fftw disabled, use ooura
+    pass
 
   # optional dependancies
   if (Options.options.enable_jack == True):
@@ -191,6 +198,5 @@ def build_tests(bld):
     # phasevoc-jack also needs jack 
     if str(target_name).endswith('test-phasevoc-jack.c'):
       this_target.includes = ['src', 'examples']
-      this_target.use = ['aubio']
       this_target.uselib = ['JACK']
       this_target.target += ' examples/jackio.c'