changeset 140:67f6b6e63d45

added Ooura implementation to repository
author Jamie Bullock <jamie@jamiebullock.com>
date Mon, 07 Jan 2013 16:27:15 +0000
parents cd6b321218f2
children e4f704649c50
files autogen.sh configure.ac doc/documentation.doxygen.in examples/simpletest/simpletest.c src/Makefile.am src/delta.c src/descriptors.c src/fftsg.c src/fftsg.h src/fini.c src/helper.c src/init.c src/libxtract.c src/scalar.c src/vector.c src/window.c src/xtract_globals_private.h swig/java/Makefile.am swig/java/SWIG.java xtract/xtract_helper.h
diffstat 20 files changed, 5557 insertions(+), 1943 deletions(-) [+]
line wrap: on
line diff
--- a/autogen.sh	Thu Sep 13 10:56:43 2012 +0100
+++ b/autogen.sh	Mon Jan 07 16:27:15 2013 +0000
@@ -12,7 +12,7 @@
       ;;
   Darwin)
       LIBTOOLIZE=glibtoolize
-      ACLOCALARGS='-I /usr/share/aclocal -I m4'
+      ACLOCALARGS='-I m4'
       ;;
   *)  echo error: unrecognized OS
       exit 1
--- a/configure.ac	Thu Sep 13 10:56:43 2012 +0100
+++ b/configure.ac	Mon Jan 07 16:27:15 2013 +0000
@@ -2,9 +2,9 @@
 # Increment for major API changes, release status changes
 m4_define(libxtract_major_version, 0)
 # Increment for feature additions and enhancements
-m4_define(libxtract_minor_version, 6)
+m4_define(libxtract_minor_version, 7)
 # Increment for fixes 
-m4_define(libxtract_fix_version, 6)
+m4_define(libxtract_fix_version, 0)
 # Development status
 m4_define(libIntegra_dev_status, [beta])
 
@@ -14,7 +14,6 @@
 
 AC_INIT([libxtract], [libxtract_version], [libxtract-devel@lists.sourceforge.net])
 AC_DEFINE(LIBXTRACT_VERSION, libxtract_version, [LibXtract Version])
-dnl AM_INIT_AUTOMAKE($PACKAGE, $LIBXTRACT_VERSION)
 AM_INIT_AUTOMAKE(1.6)
 AM_CONFIG_HEADER(config.h)
 AC_CONFIG_MACRO_DIR([m4])
@@ -30,14 +29,6 @@
 AC_CHECK_PROG([DOXYGEN], [doxygen], [doc], [])
 AC_SUBST(DOXYGEN)
 
-AC_ARG_ENABLE(fft, 
-              [  --enable-fft    Turn fft-based fft processing on],
-              [case "${enableval}" in
-               yes) fft=true ;;
-               no)  fft=false ;;
-               *) AC_MSG_ERROR(bad value ${enableval} for --enable-fft) ;;
-           esac],[fft=false])
-
 AC_ARG_ENABLE(pd_example, 
               [  --enable-pd_example    Compile the Pure Data external example],
               [case "${enableval}" in
@@ -81,25 +72,6 @@
     echo
     ])
 
-AC_ARG_WITH(fftw3_dir,
-    [  --with-fftw3-dir=path   fftw3 header path (default=/usr/local/include) ],
-    [
-    CFLAGS="$CFLAGS -I$withval"
-    echo
-    echo "fftw3 dir is $withval"
-    echo
-    ])
-
-dnl Set FFT optimisation level
-AC_ARG_WITH(fft_optimisation,
-    [  --with-fft_optimisation=level    set fft optimistaion level (default=1)],
-    [
-    FFT_OPTIMISATION="$withval"
-    echo
-    echo "fft optimisation level is $withval"
-    echo
-    ])
-
 dnl set a specific java compiler
 AC_ARG_WITH(javac,
 	[  --with-javac=compiler  set a specific java compiler (determined automatically if not set) ],
@@ -199,28 +171,6 @@
     AC_DEFINE([BUILD_SWIG], [1], [Build the swig bindings])
 fi
 
-dnl Are we building with fftw?
-if [[ "$fft" = "true" ]] ; then
-    LDFLAGS="$LDFLAGS -lfftw3f"
-    AC_DEFINE([BUILD_FFT], [1], [Build the fft functions])
-    if test "$FFT_OPTIMISATION" = ""
-    then
-        AC_DEFINE([XTRACT_FFT_OPTIMISATION_LEVEL], [1], [fft optimisation 1])
-    else
-       # AC_SUBST(OPTIMISATION_LEVEL, "$FFT_OPTIMISATION")
-        AC_DEFINE_UNQUOTED(XTRACT_FFT_OPTIMISATION_LEVEL, ${FFT_OPTIMISATION})
-    fi
-    AC_CHECK_HEADER(fftw3.h, [have_fftw3_hdr=yes ], [
-    have_pd_hdr=no
-    echo
-    echo "no fftw3.h header found.  try with option --with-fftw3-dir=/path/to/fftw3/header"
-    echo
-    exit
-    ])
-fi
-
-AM_CONDITIONAL(BUILD_FFT, test "x${fft}" = 'xtrue')
-
 dnl Check for architecture endian-ness
 #AC_C_BIGENDIAN(bigendian=true, bigendian=false, bigendian=undefined)
 #if [[ "$is_bigendian" = "false" ]] ; then
@@ -317,11 +267,6 @@
 echo
 dnl echo you are using the ${host} architecture 
 
-if test "$fft" = "true"; then
-  echo "fft:                   yes (using fftw3f)"
-else
-  echo "fft:                   no (not using fftw3, no fft functions)"
-fi
 if test "$simpletest" = "true"; then
   echo "simpletest example:	yes"
 else
--- a/doc/documentation.doxygen.in	Thu Sep 13 10:56:43 2012 +0100
+++ b/doc/documentation.doxygen.in	Mon Jan 07 16:27:15 2013 +0000
@@ -1055,7 +1055,7 @@
 # undefined via #undef or recursively expanded use the := operator 
 # instead of the = operator.
 
-PREDEFINED             = XTRACT_FFT
+PREDEFINED             = 
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
 # this tag can be used to specify a list of macro names that should be expanded. 
--- a/examples/simpletest/simpletest.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/examples/simpletest/simpletest.c	Mon Jan 07 16:27:15 2013 +0000
@@ -53,8 +53,8 @@
     /* get the spectrum */
     argf[0] = SAMPLERATE / (float)BLOCKSIZE;
     argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
-    argf[2] = 0.f;
-    argf[3] = 0.f;
+    argf[2] = 0.f; /* No DC component */
+    argf[3] = 0.f; /* No Normalisation */
 
     xtract_init_fft(BLOCKSIZE, XTRACT_SPECTRUM);
     xtract[XTRACT_SPECTRUM]((void *)&input, BLOCKSIZE, &argf[0], (void *)&spectrum[0]);
--- a/src/Makefile.am	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/Makefile.am	Mon Jan 07 16:27:15 2013 +0000
@@ -1,13 +1,7 @@
 MAINTAINERCLEANFILES = Makefile.in
 
 SOURCES = libxtract.c descriptors.c scalar.c vector.c delta.c init.c\
-	window.c fini.c helper.c
-
-if BUILD_FFT
-FFT_DEFINE = -DXTRACT_FFT
-else
-FFT_DEFINE = 
-endif
+	window.c fini.c helper.c fftsg.c
 
 lib_LTLIBRARIES = libxtract.la
 libxtract_la_CFLAGS = $(FFT_DEFINE)
--- a/src/delta.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/delta.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -24,14 +24,16 @@
 
 #include "xtract/libxtract.h"
 
-int xtract_flux(const float *data, const int N, const void *argv , float *result){
+int xtract_flux(const float *data, const int N, const void *argv , float *result)
+{
 
     /* FIX: don't be lazy -- take the lnorm of the difference vector! */
     return xtract_lnorm(data, N, argv, result);
 
 }
 
-int xtract_lnorm(const float *data, const int N, const void *argv , float *result){
+int xtract_lnorm(const float *data, const int N, const void *argv , float *result)
+{
 
     int n,
         type;
@@ -45,18 +47,20 @@
 
     *result = 0.f;
 
-    switch(type){
+    switch(type)
+    {
 
-        case XTRACT_POSITIVE_SLOPE:
-            for(n = 0; n < N; n++){
-                if(data[n] > 0)
-                    *result += powf(data[n], order);
-            }
-            break;
-        default:
-            for(n = 0; n < N; n++)
+    case XTRACT_POSITIVE_SLOPE:
+        for(n = 0; n < N; n++)
+        {
+            if(data[n] > 0)
                 *result += powf(data[n], order);
-            break;
+        }
+        break;
+    default:
+        for(n = 0; n < N; n++)
+            *result += powf(data[n], order);
+        break;
 
     }
 
@@ -66,19 +70,22 @@
 
 }
 
-int xtract_attack_time(const float *data, const int N, const void *argv , float *result){
+int xtract_attack_time(const float *data, const int N, const void *argv , float *result)
+{
 
     return XTRACT_FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_decay_time(const float *data, const int N, const void *argv, float *result){
+int xtract_decay_time(const float *data, const int N, const void *argv, float *result)
+{
 
     return XTRACT_FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_difference_vector(const float *data, const int N, const void *argv, float *result){
+int xtract_difference_vector(const float *data, const int N, const void *argv, float *result)
+{
 
     const float *frame1,
           *frame2;
--- a/src/descriptors.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/descriptors.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -24,13 +24,14 @@
 #include <string.h>
 #define XTRACT
 
-xtract_function_descriptor_t *xtract_make_descriptors(void){
+xtract_function_descriptor_t *xtract_make_descriptors(void)
+{
 
     int f , F;
-    char *name, *p_name, *desc, *p_desc, *author; 
+    char *name, *p_name, *desc, *p_desc, *author;
     float *argv_min, *argv_max, *argv_def, *result_min, *result_max;
     int *argc, *year, *argv_donor;
-    xtract_vector_t *data_format, *result_format; 
+    xtract_vector_t *data_format, *result_format;
     xtract_unit_t *data_unit, *argv_unit, *result_unit;
     xtract_bool_t *is_scalar, *is_delta;
     xtract_function_descriptor_t *fd, *d;
@@ -42,7 +43,8 @@
 
     /* FIX - this file probably needs a rewrite for readability */
 
-    while(f--){
+    while(f--)
+    {
 
         d = &fd[f];
         d->id = f;
@@ -54,396 +56,400 @@
         argv_def = &d->argv.def[0];
         argv_unit = &d->argv.unit[0];
 
-        switch (f) {
+        switch (f)
+        {
             /* argc = 1 */
-            case XTRACT_VARIANCE:
-            case XTRACT_SPECTRAL_VARIANCE:
-            case XTRACT_STANDARD_DEVIATION:
-            case XTRACT_DIFFERENCE_VECTOR: 
-            case XTRACT_AVERAGE_DEVIATION:
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+        case XTRACT_VARIANCE:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_DIFFERENCE_VECTOR:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_TONALITY:
-            case XTRACT_MFCC:
-            case XTRACT_LPC:
-            case XTRACT_LPCC:
-                *argv_min = XTRACT_ANY;
-                *argv_max = XTRACT_ANY;
-                *argv_def = XTRACT_ANY;
-                *argv_unit = XTRACT_DBFS;
-                break;
-            case XTRACT_SPECTRAL_INHARMONICITY:
-                *argv_min = 0.f;
-                *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
-                *argv_def = XTRACT_FUNDAMENTAL_DEFAULT;
-                *argv_unit = XTRACT_HERTZ;
-                break;
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-                *argv_min = XTRACT_SR_LOWER_LIMIT;
-                *argv_max = XTRACT_SR_UPPER_LIMIT;
-                *argv_def = XTRACT_SR_DEFAULT; 
-                *argv_unit = XTRACT_HERTZ;
-                break;
-            case XTRACT_FLATNESS_DB:
-                *argv_min = 0;
-                *argv_max = 1.0;
-                *argv_def = XTRACT_ANY;
-                *argv_unit = XTRACT_DBFS;
-                break;
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_TONALITY:
+        case XTRACT_MFCC:
+        case XTRACT_LPC:
+        case XTRACT_LPCC:
+            *argv_min = XTRACT_ANY;
+            *argv_max = XTRACT_ANY;
+            *argv_def = XTRACT_ANY;
+            *argv_unit = XTRACT_DBFS;
+            break;
+        case XTRACT_SPECTRAL_INHARMONICITY:
+            *argv_min = 0.f;
+            *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
+            *argv_def = XTRACT_FUNDAMENTAL_DEFAULT;
+            *argv_unit = XTRACT_HERTZ;
+            break;
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+            *argv_min = XTRACT_SR_LOWER_LIMIT;
+            *argv_max = XTRACT_SR_UPPER_LIMIT;
+            *argv_def = XTRACT_SR_DEFAULT;
+            *argv_unit = XTRACT_HERTZ;
+            break;
+        case XTRACT_FLATNESS_DB:
+            *argv_min = 0;
+            *argv_max = 1.0;
+            *argv_def = XTRACT_ANY;
+            *argv_unit = XTRACT_DBFS;
+            break;
             /* argc = 2 */;
-            case XTRACT_ROLLOFF:
-                *argv_min  = XTRACT_FFT_BANDS_MIN;
-                *argv_max = XTRACT_FFT_BANDS_MAX;
-                *argv_def = XTRACT_SPEC_BW_DEF ;
-                *argv_unit = XTRACT_HERTZ;
-                *(argv_min + 1) = 0.f;
-                *(argv_max + 1) = 100.f;
-                *(argv_def + 1) = 95.f;
-                *(argv_unit + 1) = XTRACT_PERCENT;
-                break;
-            case XTRACT_PEAK_SPECTRUM:
-                *argv_min  = XTRACT_SR_LOWER_LIMIT / 2; 
-                *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
-                *argv_def = XTRACT_SR_DEFAULT / 2;
-                *argv_unit = XTRACT_HERTZ;
-                *(argv_min + 1) = 0.f;
-                *(argv_max + 1) = 100.f ;
-                *(argv_def + 1) = 10.f ;
-                *(argv_unit + 1) = XTRACT_PERCENT;
-                break;
-            case XTRACT_HARMONIC_SPECTRUM:
-                *argv_min = 0.f;
-                *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
-                *argv_def = XTRACT_FUNDAMENTAL_DEFAULT;
-                *argv_unit = XTRACT_HERTZ;
-                *(argv_min + 1) = 0.f;
-                *(argv_max + 1) = 1.f ;
-                *(argv_def + 1) = .1f ;
-                *(argv_unit + 1) = XTRACT_NONE;
-                break;
-            case XTRACT_NOISINESS:
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
-            case XTRACT_CREST:
-                *argv_min = XTRACT_NONE;
-                *argv_max = XTRACT_NONE;
-                *argv_def = XTRACT_NONE;
-                *argv_unit = XTRACT_NONE;
-                *(argv_min + 1) = XTRACT_NONE;
-                *(argv_max + 1) = XTRACT_NONE;
-                *(argv_def + 1) = XTRACT_NONE;
-                *(argv_unit + 1) = XTRACT_NONE;
-                break;
+        case XTRACT_ROLLOFF:
+            *argv_min  = XTRACT_FFT_BANDS_MIN;
+            *argv_max = XTRACT_FFT_BANDS_MAX;
+            *argv_def = XTRACT_SPEC_BW_DEF ;
+            *argv_unit = XTRACT_HERTZ;
+            *(argv_min + 1) = 0.f;
+            *(argv_max + 1) = 100.f;
+            *(argv_def + 1) = 95.f;
+            *(argv_unit + 1) = XTRACT_PERCENT;
+            break;
+        case XTRACT_PEAK_SPECTRUM:
+            *argv_min  = XTRACT_SR_LOWER_LIMIT / 2;
+            *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
+            *argv_def = XTRACT_SR_DEFAULT / 2;
+            *argv_unit = XTRACT_HERTZ;
+            *(argv_min + 1) = 0.f;
+            *(argv_max + 1) = 100.f ;
+            *(argv_def + 1) = 10.f ;
+            *(argv_unit + 1) = XTRACT_PERCENT;
+            break;
+        case XTRACT_HARMONIC_SPECTRUM:
+            *argv_min = 0.f;
+            *argv_max = XTRACT_SR_UPPER_LIMIT / 2;
+            *argv_def = XTRACT_FUNDAMENTAL_DEFAULT;
+            *argv_unit = XTRACT_HERTZ;
+            *(argv_min + 1) = 0.f;
+            *(argv_max + 1) = 1.f ;
+            *(argv_def + 1) = .1f ;
+            *(argv_unit + 1) = XTRACT_NONE;
+            break;
+        case XTRACT_NOISINESS:
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_CREST:
+            *argv_min = XTRACT_NONE;
+            *argv_max = XTRACT_NONE;
+            *argv_def = XTRACT_NONE;
+            *argv_unit = XTRACT_NONE;
+            *(argv_min + 1) = XTRACT_NONE;
+            *(argv_max + 1) = XTRACT_NONE;
+            *(argv_def + 1) = XTRACT_NONE;
+            *(argv_unit + 1) = XTRACT_NONE;
+            break;
             /* argc = 4 */
-            case XTRACT_SPECTRUM:
-                *argv_min  = XTRACT_SR_LOWER_LIMIT / XTRACT_FFT_BANDS_MIN; 
-                *argv_max = XTRACT_SR_UPPER_LIMIT / XTRACT_FFT_BANDS_MAX;
-                *argv_def = XTRACT_SR_DEFAULT / XTRACT_FFT_BANDS_DEF;
-                *argv_unit = XTRACT_HERTZ;
-                *(argv_min + 1) = 0;
-                *(argv_max + 1) = 3 ;
-                *(argv_def + 1) = 0;
-                *(argv_unit + 1) = XTRACT_NONE;
-                *(argv_min + 2) = 0;
-                *(argv_max + 2) = 1;
-                *(argv_def + 2) = 0;
-                *(argv_unit + 2) = XTRACT_NONE;
-                *(argv_min + 3) = 0;
-                *(argv_max + 3) = 1;
-                *(argv_def + 3) = 0;
-                *(argv_unit + 3) = XTRACT_NONE;
-                break;
-            case XTRACT_SUBBANDS:
-                *argv_min  = XTRACT_ANY; 
-                *argv_max = XTRACT_ANY;
-                *argv_def = XTRACT_MEAN;
-                *argv_unit = XTRACT_NONE;
-                *(argv_min + 1) = 1;
-                *(argv_max + 1) = 16384;
-                *(argv_def + 1) = 4;
-                *(argv_unit + 1) = XTRACT_NONE;
-                *(argv_min + 2) = 0;
-                *(argv_max + 2) = 32;
-                *(argv_def + 2) = 0;
-                *(argv_unit + 2) = XTRACT_NONE;
-                *(argv_min + 3) = 0;
-                *(argv_max + 3) = XTRACT_ANY;
-                *(argv_def + 3) = 0;
-                *(argv_unit + 3) = XTRACT_BINS;
-                break;
-            case XTRACT_BARK_COEFFICIENTS:
-                /* BARK_COEFFICIENTS is special because argc = BARK_BANDS */
-            case XTRACT_WINDOWED:
-                /* WINDOWED is special because argc = window size = N */
-            default:
-                *argv_min = XTRACT_NONE;
-                *argv_max = XTRACT_NONE;
-                *argv_def = XTRACT_NONE;
-                *argv_unit = XTRACT_NONE;
-                break;
+        case XTRACT_SPECTRUM:
+            *argv_min  = XTRACT_SR_LOWER_LIMIT / XTRACT_FFT_BANDS_MIN;
+            *argv_max = XTRACT_SR_UPPER_LIMIT / XTRACT_FFT_BANDS_MAX;
+            *argv_def = XTRACT_SR_DEFAULT / XTRACT_FFT_BANDS_DEF;
+            *argv_unit = XTRACT_HERTZ;
+            *(argv_min + 1) = 0;
+            *(argv_max + 1) = 3 ;
+            *(argv_def + 1) = 0;
+            *(argv_unit + 1) = XTRACT_NONE;
+            *(argv_min + 2) = 0;
+            *(argv_max + 2) = 1;
+            *(argv_def + 2) = 0;
+            *(argv_unit + 2) = XTRACT_NONE;
+            *(argv_min + 3) = 0;
+            *(argv_max + 3) = 1;
+            *(argv_def + 3) = 0;
+            *(argv_unit + 3) = XTRACT_NONE;
+            break;
+        case XTRACT_SUBBANDS:
+            *argv_min  = XTRACT_ANY;
+            *argv_max = XTRACT_ANY;
+            *argv_def = XTRACT_MEAN;
+            *argv_unit = XTRACT_NONE;
+            *(argv_min + 1) = 1;
+            *(argv_max + 1) = 16384;
+            *(argv_def + 1) = 4;
+            *(argv_unit + 1) = XTRACT_NONE;
+            *(argv_min + 2) = 0;
+            *(argv_max + 2) = 32;
+            *(argv_def + 2) = 0;
+            *(argv_unit + 2) = XTRACT_NONE;
+            *(argv_min + 3) = 0;
+            *(argv_max + 3) = XTRACT_ANY;
+            *(argv_def + 3) = 0;
+            *(argv_unit + 3) = XTRACT_BINS;
+            break;
+        case XTRACT_BARK_COEFFICIENTS:
+            /* BARK_COEFFICIENTS is special because argc = BARK_BANDS */
+        case XTRACT_WINDOWED:
+            /* WINDOWED is special because argc = window size = N */
+        default:
+            *argv_min = XTRACT_NONE;
+            *argv_max = XTRACT_NONE;
+            *argv_def = XTRACT_NONE;
+            *argv_unit = XTRACT_NONE;
+            break;
         }
 
         argv_donor = &d->argv.donor[0];
 
-        switch (f) {
+        switch (f)
+        {
             /* argc = 1 */
-            case XTRACT_VARIANCE:
-                *argv_donor = XTRACT_MEAN;
-                break;
-            case XTRACT_SPECTRAL_VARIANCE:
-                *argv_donor = XTRACT_SPECTRAL_MEAN;
-                break;
-            case XTRACT_STANDARD_DEVIATION:
-                *argv_donor = XTRACT_VARIANCE;
-                break;
-            case XTRACT_AVERAGE_DEVIATION:
-                *argv_donor = XTRACT_MEAN;
-                break;
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
-                *argv_donor = XTRACT_SPECTRAL_VARIANCE;
-                break;
+        case XTRACT_VARIANCE:
+            *argv_donor = XTRACT_MEAN;
+            break;
+        case XTRACT_SPECTRAL_VARIANCE:
+            *argv_donor = XTRACT_SPECTRAL_MEAN;
+            break;
+        case XTRACT_STANDARD_DEVIATION:
+            *argv_donor = XTRACT_VARIANCE;
+            break;
+        case XTRACT_AVERAGE_DEVIATION:
+            *argv_donor = XTRACT_MEAN;
+            break;
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+            *argv_donor = XTRACT_SPECTRAL_VARIANCE;
+            break;
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION:
                 *argv_donor = XTRACT_SPECTRAL_MEAN;
                 break; */
-            case XTRACT_SPECTRAL_INHARMONICITY:
-                *argv_donor = XTRACT_FAILSAFE_F0;
-                break;
-            case XTRACT_FLATNESS_DB:
-                *argv_donor = XTRACT_FLATNESS;
-                break;
-            case XTRACT_TONALITY:
-                *argv_donor = XTRACT_FLATNESS_DB;
-                break;
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-                *argv_donor = XTRACT_ANY;
-                break;
-            case XTRACT_MFCC:
-                *argv_donor = XTRACT_INIT_MFCC;
-                break;
-                /* argc = 2 */;
-            case XTRACT_ROLLOFF:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_FLUX:
-            case XTRACT_LNORM:
-                *argv_donor = XTRACT_ANY;
-                *(argv_donor + 1) = XTRACT_ANY;
-                break;
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
-                *argv_donor = XTRACT_MEAN;
-                *(argv_donor + 1) = XTRACT_STANDARD_DEVIATION;
-                break;
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
-                *argv_donor = XTRACT_SPECTRAL_MEAN;
-                *(argv_donor + 1) = XTRACT_SPECTRAL_STANDARD_DEVIATION;
-                break;
-            case XTRACT_HARMONIC_SPECTRUM:
-                *argv_donor = XTRACT_FAILSAFE_F0;
-                *(argv_donor + 1) = XTRACT_ANY;
-                break;
-            case XTRACT_NOISINESS:
-                *argv_donor = XTRACT_SUM;
-                *(argv_donor + 1) = XTRACT_SUM;
-                break;
-            case XTRACT_CREST:
-                *argv_donor = XTRACT_HIGHEST_VALUE;
-                *(argv_donor + 1) = XTRACT_MEAN;
-                break;
-                /* argc = 4 */
-            case XTRACT_SPECTRUM:
-                *argv_donor = XTRACT_ANY;
-                *(argv_donor + 1) = XTRACT_ANY;
-                *(argv_donor + 2) = XTRACT_ANY;
-                *(argv_donor + 3) = XTRACT_ANY;
-                break;
-            case XTRACT_SUBBANDS:
-                *argv_donor = XTRACT_ANY;
-                *(argv_donor + 1) = XTRACT_ANY;
-                *(argv_donor + 2) = XTRACT_ANY;
-                *(argv_donor + 3) = XTRACT_ANY;
-                break;
+        case XTRACT_SPECTRAL_INHARMONICITY:
+            *argv_donor = XTRACT_FAILSAFE_F0;
+            break;
+        case XTRACT_FLATNESS_DB:
+            *argv_donor = XTRACT_FLATNESS;
+            break;
+        case XTRACT_TONALITY:
+            *argv_donor = XTRACT_FLATNESS_DB;
+            break;
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+            *argv_donor = XTRACT_ANY;
+            break;
+        case XTRACT_MFCC:
+            *argv_donor = XTRACT_INIT_MFCC;
+            break;
+            /* argc = 2 */;
+        case XTRACT_ROLLOFF:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+            *argv_donor = XTRACT_ANY;
+            *(argv_donor + 1) = XTRACT_ANY;
+            break;
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+            *argv_donor = XTRACT_MEAN;
+            *(argv_donor + 1) = XTRACT_STANDARD_DEVIATION;
+            break;
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+            *argv_donor = XTRACT_SPECTRAL_MEAN;
+            *(argv_donor + 1) = XTRACT_SPECTRAL_STANDARD_DEVIATION;
+            break;
+        case XTRACT_HARMONIC_SPECTRUM:
+            *argv_donor = XTRACT_FAILSAFE_F0;
+            *(argv_donor + 1) = XTRACT_ANY;
+            break;
+        case XTRACT_NOISINESS:
+            *argv_donor = XTRACT_SUM;
+            *(argv_donor + 1) = XTRACT_SUM;
+            break;
+        case XTRACT_CREST:
+            *argv_donor = XTRACT_HIGHEST_VALUE;
+            *(argv_donor + 1) = XTRACT_MEAN;
+            break;
+            /* argc = 4 */
+        case XTRACT_SPECTRUM:
+            *argv_donor = XTRACT_ANY;
+            *(argv_donor + 1) = XTRACT_ANY;
+            *(argv_donor + 2) = XTRACT_ANY;
+            *(argv_donor + 3) = XTRACT_ANY;
+            break;
+        case XTRACT_SUBBANDS:
+            *argv_donor = XTRACT_ANY;
+            *(argv_donor + 1) = XTRACT_ANY;
+            *(argv_donor + 2) = XTRACT_ANY;
+            *(argv_donor + 3) = XTRACT_ANY;
+            break;
             /* BARK_BANDS */
-            case XTRACT_BARK_COEFFICIENTS:
-                *argv_donor = XTRACT_INIT_BARK;
-                break;
-            case XTRACT_WINDOWED:
-                *argv_donor = XTRACT_INIT_WINDOWED;
-                break;
-            default:
-                *argv_donor = XTRACT_ANY;
-                break;
+        case XTRACT_BARK_COEFFICIENTS:
+            *argv_donor = XTRACT_INIT_BARK;
+            break;
+        case XTRACT_WINDOWED:
+            *argv_donor = XTRACT_INIT_WINDOWED;
+            break;
+        default:
+            *argv_donor = XTRACT_ANY;
+            break;
         }
 
         data_format = &d->data.format;
 
-        switch(f){
+        switch(f)
+        {
 
-            case XTRACT_MEAN: 
-            case XTRACT_VARIANCE:
-            case XTRACT_STANDARD_DEVIATION:
-            case XTRACT_AVERAGE_DEVIATION:
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_HIGHEST_VALUE:
-            case XTRACT_SUM:
-            case XTRACT_WINDOWED:
-                *data_format = XTRACT_ARBITRARY_SERIES;
-                break;
-            case XTRACT_SPECTRAL_MEAN:
-            case XTRACT_SPECTRAL_VARIANCE:
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+        case XTRACT_MEAN:
+        case XTRACT_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_HIGHEST_VALUE:
+        case XTRACT_SUM:
+        case XTRACT_WINDOWED:
+            *data_format = XTRACT_ARBITRARY_SERIES;
+            break;
+        case XTRACT_SPECTRAL_MEAN:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
-            case XTRACT_SPECTRAL_CENTROID:
-            case XTRACT_SPECTRAL_SLOPE:
-                *data_format = XTRACT_SPECTRAL;     
-                break;
-            case XTRACT_ROLLOFF:
-            case XTRACT_NOISINESS:
-            case XTRACT_BARK_COEFFICIENTS:
-            case XTRACT_CREST:
-            case XTRACT_IRREGULARITY_K:
-            case XTRACT_IRREGULARITY_J:
-            case XTRACT_SMOOTHNESS:
-            case XTRACT_FLATNESS:
-            case XTRACT_SPREAD:
-            case XTRACT_POWER:
-            case XTRACT_HPS:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_SUBBANDS:
-            case XTRACT_MFCC:
-                *data_format = XTRACT_SPECTRAL_MAGNITUDES;
-                break;
-            case XTRACT_LPC:
-                *data_format = XTRACT_AUTOCORRELATION_COEFFS;
-                break;
-            case XTRACT_LPCC:
-                *data_format = XTRACT_LPC_COEFFS;
-                break;
-            case XTRACT_SPECTRAL_INHARMONICITY:
-            case XTRACT_HARMONIC_SPECTRUM:
-                *data_format = XTRACT_SPECTRAL_PEAKS;
-                break;
-            case XTRACT_NONZERO_COUNT:
-                *data_format = XTRACT_SPECTRAL_PEAKS_MAGNITUDES;
-                break;
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-            case XTRACT_SPECTRUM:
-            case XTRACT_AUTOCORRELATION:
-            case XTRACT_AUTOCORRELATION_FFT:
-            case XTRACT_DCT:
-            case XTRACT_AMDF:
-            case XTRACT_ASDF:
-            case XTRACT_ZCR:
-            case XTRACT_RMS_AMPLITUDE:
-            case XTRACT_FLUX: 
-            case XTRACT_LNORM: 
-                *data_format = XTRACT_AUDIO_SAMPLES;
-                break;
-            case XTRACT_TONALITY:
-            case XTRACT_FLATNESS_DB:
-                *data_format = XTRACT_NO_DATA;
-                break;
-            case XTRACT_TRISTIMULUS_1:
-            case XTRACT_TRISTIMULUS_2:
-            case XTRACT_TRISTIMULUS_3:
-            case XTRACT_ODD_EVEN_RATIO:
-                *data_format = XTRACT_SPECTRAL_HARMONICS_MAGNITUDES;
-                break;
-            case XTRACT_LOUDNESS:
-            case XTRACT_SHARPNESS:
-                *data_format = XTRACT_BARK_COEFFS;
-                break;
-            case XTRACT_DIFFERENCE_VECTOR: 
-                *data_format = XTRACT_SUBFRAMES;
-                break;
-            case XTRACT_ATTACK_TIME: 
-            case XTRACT_DECAY_TIME: 
-            default:
-                *data_format = XTRACT_NO_DATA;
-                break;
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_SPECTRAL_CENTROID:
+        case XTRACT_SPECTRAL_SLOPE:
+            *data_format = XTRACT_SPECTRAL;
+            break;
+        case XTRACT_ROLLOFF:
+        case XTRACT_NOISINESS:
+        case XTRACT_BARK_COEFFICIENTS:
+        case XTRACT_CREST:
+        case XTRACT_IRREGULARITY_K:
+        case XTRACT_IRREGULARITY_J:
+        case XTRACT_SMOOTHNESS:
+        case XTRACT_FLATNESS:
+        case XTRACT_SPREAD:
+        case XTRACT_POWER:
+        case XTRACT_HPS:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_SUBBANDS:
+        case XTRACT_MFCC:
+            *data_format = XTRACT_SPECTRAL_MAGNITUDES;
+            break;
+        case XTRACT_LPC:
+            *data_format = XTRACT_AUTOCORRELATION_COEFFS;
+            break;
+        case XTRACT_LPCC:
+            *data_format = XTRACT_LPC_COEFFS;
+            break;
+        case XTRACT_SPECTRAL_INHARMONICITY:
+        case XTRACT_HARMONIC_SPECTRUM:
+            *data_format = XTRACT_SPECTRAL_PEAKS;
+            break;
+        case XTRACT_NONZERO_COUNT:
+            *data_format = XTRACT_SPECTRAL_PEAKS_MAGNITUDES;
+            break;
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+        case XTRACT_SPECTRUM:
+        case XTRACT_AUTOCORRELATION:
+        case XTRACT_AUTOCORRELATION_FFT:
+        case XTRACT_DCT:
+        case XTRACT_AMDF:
+        case XTRACT_ASDF:
+        case XTRACT_ZCR:
+        case XTRACT_RMS_AMPLITUDE:
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+            *data_format = XTRACT_AUDIO_SAMPLES;
+            break;
+        case XTRACT_TONALITY:
+        case XTRACT_FLATNESS_DB:
+            *data_format = XTRACT_NO_DATA;
+            break;
+        case XTRACT_TRISTIMULUS_1:
+        case XTRACT_TRISTIMULUS_2:
+        case XTRACT_TRISTIMULUS_3:
+        case XTRACT_ODD_EVEN_RATIO:
+            *data_format = XTRACT_SPECTRAL_HARMONICS_MAGNITUDES;
+            break;
+        case XTRACT_LOUDNESS:
+        case XTRACT_SHARPNESS:
+            *data_format = XTRACT_BARK_COEFFS;
+            break;
+        case XTRACT_DIFFERENCE_VECTOR:
+            *data_format = XTRACT_SUBFRAMES;
+            break;
+        case XTRACT_ATTACK_TIME:
+        case XTRACT_DECAY_TIME:
+        default:
+            *data_format = XTRACT_NO_DATA;
+            break;
         }
 
         data_unit = &d->data.unit;
 
-        switch(f){
+        switch(f)
+        {
 
-            case XTRACT_MEAN: 
-            case XTRACT_VARIANCE:
-            case XTRACT_STANDARD_DEVIATION:
-            case XTRACT_AVERAGE_DEVIATION:
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_HIGHEST_VALUE:
-            case XTRACT_SUM:
-            case XTRACT_ZCR:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_TRISTIMULUS_1:
-            case XTRACT_TRISTIMULUS_2:
-            case XTRACT_TRISTIMULUS_3:
-            case XTRACT_DCT:
-            case XTRACT_AMDF:
-            case XTRACT_ASDF:
-            case XTRACT_IRREGULARITY_K:
-            case XTRACT_IRREGULARITY_J:
-            case XTRACT_ATTACK_TIME: 
-            case XTRACT_DECAY_TIME: 
-            case XTRACT_DIFFERENCE_VECTOR: 
-            case XTRACT_FLUX: 
-            case XTRACT_LNORM: 
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-            case XTRACT_MFCC:
-            case XTRACT_AUTOCORRELATION:
-            case XTRACT_AUTOCORRELATION_FFT:
-            case XTRACT_ROLLOFF:
-            case XTRACT_NOISINESS:
-            case XTRACT_CREST:
-            case XTRACT_FLATNESS:
-            case XTRACT_FLATNESS_DB:
-            case XTRACT_POWER:
-            case XTRACT_BARK_COEFFICIENTS:
-            case XTRACT_RMS_AMPLITUDE:
-            case XTRACT_SMOOTHNESS:
-            case XTRACT_SPREAD:
-            case XTRACT_SHARPNESS:
-            case XTRACT_HPS:
-            case XTRACT_SPECTRUM:
-            case XTRACT_TONALITY:
-            case XTRACT_LOUDNESS:
-            case XTRACT_NONZERO_COUNT:
-            case XTRACT_LPC:
-            case XTRACT_LPCC:
-            case XTRACT_WINDOWED:
-            case XTRACT_SUBBANDS:
-                *data_unit = XTRACT_ANY;
-                break;
-            case XTRACT_SPECTRAL_MEAN:
-            case XTRACT_SPECTRAL_VARIANCE:
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+        case XTRACT_MEAN:
+        case XTRACT_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_HIGHEST_VALUE:
+        case XTRACT_SUM:
+        case XTRACT_ZCR:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_TRISTIMULUS_1:
+        case XTRACT_TRISTIMULUS_2:
+        case XTRACT_TRISTIMULUS_3:
+        case XTRACT_DCT:
+        case XTRACT_AMDF:
+        case XTRACT_ASDF:
+        case XTRACT_IRREGULARITY_K:
+        case XTRACT_IRREGULARITY_J:
+        case XTRACT_ATTACK_TIME:
+        case XTRACT_DECAY_TIME:
+        case XTRACT_DIFFERENCE_VECTOR:
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+        case XTRACT_MFCC:
+        case XTRACT_AUTOCORRELATION:
+        case XTRACT_AUTOCORRELATION_FFT:
+        case XTRACT_ROLLOFF:
+        case XTRACT_NOISINESS:
+        case XTRACT_CREST:
+        case XTRACT_FLATNESS:
+        case XTRACT_FLATNESS_DB:
+        case XTRACT_POWER:
+        case XTRACT_BARK_COEFFICIENTS:
+        case XTRACT_RMS_AMPLITUDE:
+        case XTRACT_SMOOTHNESS:
+        case XTRACT_SPREAD:
+        case XTRACT_SHARPNESS:
+        case XTRACT_HPS:
+        case XTRACT_SPECTRUM:
+        case XTRACT_TONALITY:
+        case XTRACT_LOUDNESS:
+        case XTRACT_NONZERO_COUNT:
+        case XTRACT_LPC:
+        case XTRACT_LPCC:
+        case XTRACT_WINDOWED:
+        case XTRACT_SUBBANDS:
+            *data_unit = XTRACT_ANY;
+            break;
+        case XTRACT_SPECTRAL_MEAN:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
-            case XTRACT_SPECTRAL_CENTROID:
-            case XTRACT_SPECTRAL_SLOPE:
-            case XTRACT_HARMONIC_SPECTRUM:
-            case XTRACT_SPECTRAL_INHARMONICITY:
-                *data_unit = XTRACT_ANY_AMPLITUDE_HERTZ;
-                break;
-            case XTRACT_ODD_EVEN_RATIO:
-                *data_unit = XTRACT_HERTZ;
-                break;
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_SPECTRAL_CENTROID:
+        case XTRACT_SPECTRAL_SLOPE:
+        case XTRACT_HARMONIC_SPECTRUM:
+        case XTRACT_SPECTRAL_INHARMONICITY:
+            *data_unit = XTRACT_ANY_AMPLITUDE_HERTZ;
+            break;
+        case XTRACT_ODD_EVEN_RATIO:
+            *data_unit = XTRACT_HERTZ;
+            break;
         }
 
         name = d->algo.name;
@@ -456,864 +462,872 @@
         strcpy(author, "");
         *year = 0;
 
-        switch(f){
-            case XTRACT_MEAN: 
-                strcpy(name, "mean");
-                strcpy(p_name, "Mean");
-                strcpy(desc, "Extract the mean of an input vector");
-                strcpy(p_desc, "Extract the mean of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_VARIANCE:
-                strcpy(name, "variance");
-                strcpy(p_name, "Variance");
-                strcpy(desc, "Extract the variance of an input vector");
-                strcpy(p_desc, "Extract the variance of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_STANDARD_DEVIATION:
-                strcpy(name, "standard_deviation");
-                strcpy(p_name, "Standard Deviation");
-                strcpy(desc, 
-                        "Extract the standard deviation of an input vector");
-                strcpy(p_desc, 
-                        "Extract the standard deviation of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_AVERAGE_DEVIATION:
-                strcpy(name, "average_deviation");
-                strcpy(p_name, "Average Deviation");
-                strcpy(desc, 
-                        "Extract the average deviation of an input vector");
-                strcpy(p_desc, 
-                        "Extract the average deviation of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_SKEWNESS:
-                strcpy(name, "skewness");
-                strcpy(p_name, "Skewness");
-                strcpy(desc, 
-                        "Extract the skewness of an input vector");
-                strcpy(p_desc, 
-                        "Extract the skewness of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_KURTOSIS:
-                strcpy(name, "kurtosis");
-                strcpy(p_name, "Kurtosis");
-                strcpy(desc, 
-                        "Extract the kurtosis of an input vector");
-                strcpy(p_desc, 
-                        "Extract the kurtosis of a range of values");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_MEAN: 
-                strcpy(name, "spectral_mean");
-                strcpy(p_name, "Spectral Mean");
-                strcpy(desc, "Extract the mean of an input spectrum");
-                strcpy(p_desc, "Extract the mean of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_VARIANCE:
-                strcpy(name, "spectral_variance");
-                strcpy(p_name, "Spectral Variance");
-                strcpy(desc, "Extract the variance of an input spectrum");
-                strcpy(p_desc, "Extract the variance of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
-                strcpy(name, "spectral_standard_deviation");
-                strcpy(p_name, "Spectral Standard Deviation");
-                strcpy(desc, 
-                        "Extract the standard deviation of an input spectrum");
-                strcpy(p_desc, 
-                        "Extract the standard deviation of an audio spectrum");
-                strcpy(author, "");
-                break;
+        switch(f)
+        {
+        case XTRACT_MEAN:
+            strcpy(name, "mean");
+            strcpy(p_name, "Mean");
+            strcpy(desc, "Extract the mean of an input vector");
+            strcpy(p_desc, "Extract the mean of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_VARIANCE:
+            strcpy(name, "variance");
+            strcpy(p_name, "Variance");
+            strcpy(desc, "Extract the variance of an input vector");
+            strcpy(p_desc, "Extract the variance of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_STANDARD_DEVIATION:
+            strcpy(name, "standard_deviation");
+            strcpy(p_name, "Standard Deviation");
+            strcpy(desc,
+                   "Extract the standard deviation of an input vector");
+            strcpy(p_desc,
+                   "Extract the standard deviation of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_AVERAGE_DEVIATION:
+            strcpy(name, "average_deviation");
+            strcpy(p_name, "Average Deviation");
+            strcpy(desc,
+                   "Extract the average deviation of an input vector");
+            strcpy(p_desc,
+                   "Extract the average deviation of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_SKEWNESS:
+            strcpy(name, "skewness");
+            strcpy(p_name, "Skewness");
+            strcpy(desc,
+                   "Extract the skewness of an input vector");
+            strcpy(p_desc,
+                   "Extract the skewness of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_KURTOSIS:
+            strcpy(name, "kurtosis");
+            strcpy(p_name, "Kurtosis");
+            strcpy(desc,
+                   "Extract the kurtosis of an input vector");
+            strcpy(p_desc,
+                   "Extract the kurtosis of a range of values");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_MEAN:
+            strcpy(name, "spectral_mean");
+            strcpy(p_name, "Spectral Mean");
+            strcpy(desc, "Extract the mean of an input spectrum");
+            strcpy(p_desc, "Extract the mean of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_VARIANCE:
+            strcpy(name, "spectral_variance");
+            strcpy(p_name, "Spectral Variance");
+            strcpy(desc, "Extract the variance of an input spectrum");
+            strcpy(p_desc, "Extract the variance of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+            strcpy(name, "spectral_standard_deviation");
+            strcpy(p_name, "Spectral Standard Deviation");
+            strcpy(desc,
+                   "Extract the standard deviation of an input spectrum");
+            strcpy(p_desc,
+                   "Extract the standard deviation of an audio spectrum");
+            strcpy(author, "");
+            break;
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION:
                 strcpy(name, "spectral_average_deviation");
                 strcpy(p_name, "Spectral Average Deviation");
-                strcpy(desc, 
+                strcpy(desc,
                         "Extract the average deviation of an input spectrum");
-                strcpy(p_desc, 
+                strcpy(p_desc,
                         "Extract the average deviation of an audio spectrum");
                 strcpy(author, "");
                 break;
                 */
-            case XTRACT_ROLLOFF:
-                strcpy(name, "rolloff");
-                strcpy(p_name, "Spectral Rolloff");
-                strcpy(desc, 
-                        "Extract the rolloff point of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the rolloff point of an audio spectrum");
-                strcpy(author, "Bee Suan Ong");
-                *year = 2005;
-                break;
-            case XTRACT_SPECTRAL_INHARMONICITY:
-                strcpy(name, "spectral_inharmonicity");
-                strcpy(p_name, "Inharmonicity");
-                strcpy(desc, "Extract the inharmonicity of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the inharmonicity of an audio spectrum");
-                break;
-            case XTRACT_SPECTRUM:
-                strcpy(name, "spectrum");
-                strcpy(p_name, "Spectrum");
-                strcpy(desc, 
-                        "Extract the spectrum of an input vector");
-                strcpy(p_desc, 
-                        "Extract the spectrum of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_ODD_EVEN_RATIO:
-                strcpy(name, "odd_even_ratio");
-                strcpy(p_name, "Odd/even Harmonic Ratio");
-                strcpy(desc, 
-                        "Extract the odd-to-even harmonic ratio of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the odd-to-even harmonic ratio of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_LOWEST_VALUE:
-                strcpy(name, "lowest_value");
-                strcpy(p_name, "Lowest Value");
-                strcpy(desc, "Extract the lowest value from an input vector");
-                strcpy(p_desc, "Extract the lowest value from a given range");
-                strcpy(author, "");
-                break;
-            case XTRACT_F0:
-                strcpy(name, "f0");
-                strcpy(p_name, "Fundamental Frequency");
-                strcpy(desc, "Extract the fundamental frequency	of a signal");
-                strcpy(p_desc, 
-                        "Extract the fundamental frequency of an audio signal");
-                strcpy(author, "Jamie Bullock");
-                break;
-            case XTRACT_FAILSAFE_F0:
-                strcpy(name, "failsafe_f0");
-                strcpy(p_name, "Fundamental Frequency (failsafe)");
-                strcpy(desc, "Extract the fundamental frequency of a signal (failsafe)");
-                strcpy(p_desc, 
-                        "Extract the fundamental frequency of an audio signal (failsafe)");
-                strcpy(author, "Jamie Bullock");
-                break;
-            case XTRACT_TONALITY:
-                strcpy(name, "tonality");
-                strcpy(p_name, "Tonality");
-                strcpy(desc, "Extract the tonality of a spectrum");
-                strcpy(p_desc, "Extract the tonality an audio spectrum");
-                strcpy(author, "J. D. Johnston");
-                *year = 1988;
-                break;
-            case XTRACT_SPECTRAL_SKEWNESS:
-                strcpy(name, "spectral_skewness");
-                strcpy(p_name, "Spectral Skewness");
-                strcpy(desc, "Extract the skewness of an input spectrum");
-                strcpy(p_desc, "Extract the skewness of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_KURTOSIS:
-                strcpy(name, "spectral_kurtosis");
-                strcpy(p_name, "Spectral Kurtosis");
-                strcpy(desc, "Extract the kurtosis of an input spectrum");
-                strcpy(p_desc, "Extract the kurtosis of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_PEAK_SPECTRUM:
-                strcpy(name, "peak_spectrum");
-                strcpy(p_name, "Peak Spectrum");
-                strcpy(desc, "Extract the spectral peaks from of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral peaks from an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_HARMONIC_SPECTRUM:
-                strcpy(name, "harmonic_spectrum");
-                strcpy(p_name, "Harmonic Spectrum");
-                strcpy(desc, "Extract the harmonics from a spectrum");
-                strcpy(p_desc, "Extract the harmonics from an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_NOISINESS:
-                strcpy(name, "noisiness");
-                strcpy(p_name, "Noisiness");
-                strcpy(desc, "Extract the noisiness of a spectrum");
-                strcpy(p_desc, "Extract the noisiness of an audio  spectrum");
-                strcpy(author, "Tae Hong Park");
-                *year = 2000;
-                break;
-            case XTRACT_CREST:
-                strcpy(name, "crest");
-                strcpy(p_name, "Spectral Crest Measure");
-                strcpy(desc, 
-                        "Extract the spectral crest measure of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral crest measure of an audio spectrum");
-                strcpy(author, "Peeters");
-                *year = 2003;
-                break;
-            case XTRACT_MFCC:
-                strcpy(name, "mfcc");
-                strcpy(p_name, "Mel-Frequency Cepstral Coefficients");
-                strcpy(desc, "Extract MFCC from a spectrum");
-                strcpy(p_desc, "Extract MFCC from an audio spectrum");
-                strcpy(author, "Rabiner");
-                break;
-            case XTRACT_LPC:
-                strcpy(name, "lpc");
-                strcpy(p_name, "Linear predictive coding coefficients");
-                strcpy(desc, "Extract LPC from autocorrelation coefficients");
-                strcpy(p_desc, 
-                        "Extract LPC from autocorrelation coefficients");
-                strcpy(author, 
-                        "Rabiner and Juang as implemented by Jutta Degener");
-                *year = 1994;
-                break;
-            case XTRACT_LPCC:
-                strcpy(name, "lpcc");
-                strcpy(p_name, "Linear predictive coding cepstral coefficients");
-                strcpy(desc, "Extract LPC cepstrum from LPC coefficients");
-                strcpy(p_desc, 
-                        "Extract LPC cepstrum from LPC coefficients");
-                strcpy(author, "Rabiner and Juang");
-                *year = 1993;
-                break;
-            case XTRACT_SUBBANDS:
-                strcpy(name, "subbands");
-                strcpy(p_name, "Sub band coefficients");
-                strcpy(desc, "Extract subband coefficients from spectral magnitudes");
-                strcpy(p_desc, 
-                        "Extract subband coefficients from spectral magnitudes");
-                strcpy(author, "");
-                break;
-            case XTRACT_BARK_COEFFICIENTS:
-                strcpy(name, "bark_coefficients");
-                strcpy(p_name, "Bark Coefficients");
-                strcpy(desc, "Extract bark coefficients from a spectrum");
-                strcpy(p_desc, 
-                        "Extract bark coefficients from an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_CENTROID:
-                strcpy(name, "spectral_centroid");
-                strcpy(p_name, "Spectral Centroid");
-                strcpy(desc, "Extract the spectral centroid of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral centroid of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_IRREGULARITY_K:
-                strcpy(name, "irregularity_k");
-                strcpy(p_name, "Irregularity I");
-                strcpy(desc, "Extract the irregularity (type I) of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the irregularity (type I) of an audio spectrum");
-                strcpy(author, "Krimphoff");
-                *year = 1994;
-                break;
-            case XTRACT_IRREGULARITY_J:
-                strcpy(name, "irregularity_j");
-                strcpy(p_name, "Irregularity II");
-                strcpy(desc, "Extract the irregularity (type II) of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the irregularity (type II) of an audio spectrum");
-                strcpy(author, "Jensen");
-                *year = 1999;
-                break;
-            case XTRACT_TRISTIMULUS_1:
-                strcpy(name, "tristimulus_1");
-                strcpy(p_name, "Tristimulus I");
-                strcpy(desc, "Extract the tristimulus (type I) of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the tristimulus (type I) of an audio spectrum");
-                strcpy(author, "Pollard and Jansson");
-                *year = 1982;
-                break;
-            case XTRACT_TRISTIMULUS_2:
-                strcpy(name, "tristimulus_2");
-                strcpy(p_name, "Tristimulus II");
-                strcpy(desc, "Extract the tristimulus (type II) of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the tristimulus (type II) of an audio spectrum");
-                strcpy(author, "Pollard and Jansson");
-                *year = 1982;
-                break;
-            case XTRACT_TRISTIMULUS_3:
-                strcpy(name, "tristimulus_3");
-                strcpy(p_name, "Tristimulus III");
-                strcpy(desc, 
-                        "Extract the tristimulus (type III) of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the tristimulus (type III) of an audio spectrum");
-                strcpy(author, "Pollard and Jansson");
-                *year = 1982;
-                break;
-            case XTRACT_SMOOTHNESS:
-                strcpy(name, "smoothness");
-                strcpy(p_name, "Spectral Smoothness");
-                strcpy(desc, "Extract the spectral smoothness of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral smoothness of an audio spectrum");
-                strcpy(author, "McAdams");
-                *year = 1999;
-                break;
-            case XTRACT_FLATNESS:
-                strcpy(name, "flatness");
-                strcpy(p_name, "Spectral Flatness");
-                strcpy(desc, "Extract the spectral flatness of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral flatness of an audio spectrum");
-                strcpy(author, "Tristan Jehan");
-                *year = 2005;
-                break;
-            case XTRACT_FLATNESS_DB:
-                strcpy(name, "flatness_db");
-                strcpy(p_name, "Log Spectral Flatness");
-                strcpy(desc, "Extract the log spectral flatness of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the log spectral flatness of an audio spectrum");
-                strcpy(author, "Peeters");
-                *year = 2003;
-                break;
-            case XTRACT_SPREAD:
-                strcpy(name, "spread");
-                strcpy(p_name, "Spectral Spread");
-                strcpy(desc, "Extract the spectral spread of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral spread of an audio spectrum");
-                strcpy(author, "Norman Casagrande");
-                *year = 2005;
-                break;
-            case XTRACT_ZCR:
-                strcpy(name, "zcr");
-                strcpy(p_name, "Zero Crossing Rate");
-                strcpy(desc, "Extract the zero crossing rate of a vector");
-                strcpy(p_desc, 
-                        "Extract the zero crossing rate of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_LOUDNESS:
-                strcpy(name, "loudness");
-                strcpy(p_name, "Loudness");
-                strcpy(desc, 
-                        "Extract the loudness of a signal from its spectrum");
-                strcpy(p_desc, 
-                        "Extract the loudness of an audio signal from its spectrum");
-                strcpy(author, "Moore, Glasberg et al");
-                *year = 2005;
-                break;
-            case XTRACT_HIGHEST_VALUE:
-                strcpy(name, "highest_value");
-                strcpy(p_name, "Highest Value");
-                strcpy(desc, "Extract the highest value from an input vector");
-                strcpy(p_desc, "Extract the highest value from a given range");
-                strcpy(author, "");
-                break;
-            case XTRACT_SUM:
-                strcpy(name, "sum");
-                strcpy(p_name, "Sum of Values");
-                strcpy(desc, 
-                        "Extract the sum of the values in an input vector");
-                strcpy(p_desc, 
-                        "Extract the sum of the values in a given range");
-                strcpy(author, "");
-                break;
-            case XTRACT_RMS_AMPLITUDE:
-                strcpy(name, "rms_amplitude");
-                strcpy(p_name, "RMS Amplitude");
-                strcpy(desc, "Extract the RMS amplitude of a signal");
-                strcpy(p_desc, "Extract the RMS amplitude of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_POWER:
-                strcpy(name, "power");
-                strcpy(p_name, "Spectral Power");
-                strcpy(desc, "Extract the spectral power of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral power of an audio spectrum");
-                strcpy(author, "Bee Suan Ong");
-                *year = 2005;
-                break;
-            case XTRACT_SHARPNESS:
-                strcpy(name, "sharpness");
-                strcpy(p_name, "Spectral Sharpness");
-                strcpy(desc, "Extract the spectral sharpness of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral sharpness of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_SPECTRAL_SLOPE:
-                strcpy(name, "spectral_slope");
-                strcpy(p_name, "Spectral Slope");
-                strcpy(desc, "Extract the spectral slope of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral slope of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_HPS:
-                strcpy(name, "hps");
-                strcpy(p_name, "Harmonic Product Spectrum");
-                strcpy(desc, 
-                        "Extract the harmonic product spectrum of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the harmonic product spectrum of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_FLUX: 
-                strcpy(name, "flux");
-                strcpy(p_name, "Spectral Flux");
-                strcpy(desc, "Extract the spectral flux of a spectrum");
-                strcpy(p_desc, 
-                        "Extract the spectral flux of an audio spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_LNORM: 
-                strcpy(name, "lnorm");
-                strcpy(p_name, "L-norm");
-                strcpy(desc, "Extract the L-norm of a vector");
-                strcpy(p_desc, "Extract the L-norm of a vector");
-                strcpy(author, "");
-                break;
-            case XTRACT_ATTACK_TIME: 
-                strcpy(name, "attack_time");
-                strcpy(p_name, "Attack Time");
-                strcpy(desc, "Extract the attack time of a signal");
-                strcpy(p_desc, "Extract the attack time of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_DECAY_TIME: 
-                strcpy(name, "decay_time");
-                strcpy(p_name, "Decay Time");
-                strcpy(desc, "Extract the decay time of a signal");
-                strcpy(p_desc, "Extract the decay time of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_DIFFERENCE_VECTOR: 
-                strcpy(name, "difference_vector");
-                strcpy(p_name, "Difference vector");
-                strcpy(desc, "Extract the difference between two vectors");
-                strcpy(p_desc, "Extract the difference between two vectors");
-                strcpy(author, "");
-                break;
-            case XTRACT_AUTOCORRELATION_FFT:
-                strcpy(name, "autocorrelation_fft");
-                strcpy(p_name, "Autocorrelation (FFT method)");
-                strcpy(desc, "Extract the autocorrelation of a signal (fft method)");
-                strcpy(p_desc, "Extract the autocorrelation of an audio signal (fft method)");
-                strcpy(author, "");
-                break;
-            case XTRACT_DCT:
-                strcpy(name, "dct");
-                strcpy(p_name, "Discrete Cosine Transform");
-                strcpy(desc, "Extract the DCT of a signal");
-                strcpy(p_desc, "Extract the DCT of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_AUTOCORRELATION:
-                strcpy(name, "autocorrelation");
-                strcpy(p_name, "Autocorrelation");
-                strcpy(desc, "Extract the autocorrelation of a signal");
-                strcpy(p_desc, 
-                        "Extract the autocorrelation of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_AMDF:
-                strcpy(name, "amdf");
-                strcpy(p_name, "Average Magnitude Difference Function");
-                strcpy(desc, "Extract the AMDF of a signal");
-                strcpy(p_desc, "Extract the AMDF of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_ASDF:
-                strcpy(name, "asdf");
-                strcpy(p_name, "Average Squared Difference Function");
-                strcpy(desc, "Extract the ASDF of a signal");
-                strcpy(p_desc, "Extract the ASDF of an audio signal");
-                strcpy(author, "");
-                break;
-            case XTRACT_NONZERO_COUNT:
-                strcpy(name, "nonzero_count");
-                strcpy(p_name, "Non-zero count");
-                strcpy(desc, 
-                        "Extract the number of non-zero elements in the input vector");
-                strcpy(p_desc, 
-                        "Extract the number of non-zero elements in an input spectrum");
-                strcpy(author, "");
-                break;
-            case XTRACT_WINDOWED:
-                strcpy(name, "windowed");
-                strcpy(p_name, "Windowed frame");
-                strcpy(desc, "Apply a window function to a frame of data");
-                strcpy(p_desc, "Apply a window function to a frame of data");
-                strcpy(author, "");
-                break;
-            default:
-                strcpy(name, "");
-                strcpy(p_name, "");
-                strcpy(desc, "");
-                strcpy(p_desc, "");
-                strcpy(author, "");
-                break;
+        case XTRACT_ROLLOFF:
+            strcpy(name, "rolloff");
+            strcpy(p_name, "Spectral Rolloff");
+            strcpy(desc,
+                   "Extract the rolloff point of a spectrum");
+            strcpy(p_desc,
+                   "Extract the rolloff point of an audio spectrum");
+            strcpy(author, "Bee Suan Ong");
+            *year = 2005;
+            break;
+        case XTRACT_SPECTRAL_INHARMONICITY:
+            strcpy(name, "spectral_inharmonicity");
+            strcpy(p_name, "Inharmonicity");
+            strcpy(desc, "Extract the inharmonicity of a spectrum");
+            strcpy(p_desc,
+                   "Extract the inharmonicity of an audio spectrum");
+            break;
+        case XTRACT_SPECTRUM:
+            strcpy(name, "spectrum");
+            strcpy(p_name, "Spectrum");
+            strcpy(desc,
+                   "Extract the spectrum of an input vector");
+            strcpy(p_desc,
+                   "Extract the spectrum of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_ODD_EVEN_RATIO:
+            strcpy(name, "odd_even_ratio");
+            strcpy(p_name, "Odd/even Harmonic Ratio");
+            strcpy(desc,
+                   "Extract the odd-to-even harmonic ratio of a spectrum");
+            strcpy(p_desc,
+                   "Extract the odd-to-even harmonic ratio of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_LOWEST_VALUE:
+            strcpy(name, "lowest_value");
+            strcpy(p_name, "Lowest Value");
+            strcpy(desc, "Extract the lowest value from an input vector");
+            strcpy(p_desc, "Extract the lowest value from a given range");
+            strcpy(author, "");
+            break;
+        case XTRACT_F0:
+            strcpy(name, "f0");
+            strcpy(p_name, "Fundamental Frequency");
+            strcpy(desc, "Extract the fundamental frequency	of a signal");
+            strcpy(p_desc,
+                   "Extract the fundamental frequency of an audio signal");
+            strcpy(author, "Jamie Bullock");
+            break;
+        case XTRACT_FAILSAFE_F0:
+            strcpy(name, "failsafe_f0");
+            strcpy(p_name, "Fundamental Frequency (failsafe)");
+            strcpy(desc, "Extract the fundamental frequency of a signal (failsafe)");
+            strcpy(p_desc,
+                   "Extract the fundamental frequency of an audio signal (failsafe)");
+            strcpy(author, "Jamie Bullock");
+            break;
+        case XTRACT_TONALITY:
+            strcpy(name, "tonality");
+            strcpy(p_name, "Tonality");
+            strcpy(desc, "Extract the tonality of a spectrum");
+            strcpy(p_desc, "Extract the tonality an audio spectrum");
+            strcpy(author, "J. D. Johnston");
+            *year = 1988;
+            break;
+        case XTRACT_SPECTRAL_SKEWNESS:
+            strcpy(name, "spectral_skewness");
+            strcpy(p_name, "Spectral Skewness");
+            strcpy(desc, "Extract the skewness of an input spectrum");
+            strcpy(p_desc, "Extract the skewness of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_KURTOSIS:
+            strcpy(name, "spectral_kurtosis");
+            strcpy(p_name, "Spectral Kurtosis");
+            strcpy(desc, "Extract the kurtosis of an input spectrum");
+            strcpy(p_desc, "Extract the kurtosis of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_PEAK_SPECTRUM:
+            strcpy(name, "peak_spectrum");
+            strcpy(p_name, "Peak Spectrum");
+            strcpy(desc, "Extract the spectral peaks from of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral peaks from an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_HARMONIC_SPECTRUM:
+            strcpy(name, "harmonic_spectrum");
+            strcpy(p_name, "Harmonic Spectrum");
+            strcpy(desc, "Extract the harmonics from a spectrum");
+            strcpy(p_desc, "Extract the harmonics from an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_NOISINESS:
+            strcpy(name, "noisiness");
+            strcpy(p_name, "Noisiness");
+            strcpy(desc, "Extract the noisiness of a spectrum");
+            strcpy(p_desc, "Extract the noisiness of an audio  spectrum");
+            strcpy(author, "Tae Hong Park");
+            *year = 2000;
+            break;
+        case XTRACT_CREST:
+            strcpy(name, "crest");
+            strcpy(p_name, "Spectral Crest Measure");
+            strcpy(desc,
+                   "Extract the spectral crest measure of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral crest measure of an audio spectrum");
+            strcpy(author, "Peeters");
+            *year = 2003;
+            break;
+        case XTRACT_MFCC:
+            strcpy(name, "mfcc");
+            strcpy(p_name, "Mel-Frequency Cepstral Coefficients");
+            strcpy(desc, "Extract MFCC from a spectrum");
+            strcpy(p_desc, "Extract MFCC from an audio spectrum");
+            strcpy(author, "Rabiner");
+            break;
+        case XTRACT_LPC:
+            strcpy(name, "lpc");
+            strcpy(p_name, "Linear predictive coding coefficients");
+            strcpy(desc, "Extract LPC from autocorrelation coefficients");
+            strcpy(p_desc,
+                   "Extract LPC from autocorrelation coefficients");
+            strcpy(author,
+                   "Rabiner and Juang as implemented by Jutta Degener");
+            *year = 1994;
+            break;
+        case XTRACT_LPCC:
+            strcpy(name, "lpcc");
+            strcpy(p_name, "Linear predictive coding cepstral coefficients");
+            strcpy(desc, "Extract LPC cepstrum from LPC coefficients");
+            strcpy(p_desc,
+                   "Extract LPC cepstrum from LPC coefficients");
+            strcpy(author, "Rabiner and Juang");
+            *year = 1993;
+            break;
+        case XTRACT_SUBBANDS:
+            strcpy(name, "subbands");
+            strcpy(p_name, "Sub band coefficients");
+            strcpy(desc, "Extract subband coefficients from spectral magnitudes");
+            strcpy(p_desc,
+                   "Extract subband coefficients from spectral magnitudes");
+            strcpy(author, "");
+            break;
+        case XTRACT_BARK_COEFFICIENTS:
+            strcpy(name, "bark_coefficients");
+            strcpy(p_name, "Bark Coefficients");
+            strcpy(desc, "Extract bark coefficients from a spectrum");
+            strcpy(p_desc,
+                   "Extract bark coefficients from an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_CENTROID:
+            strcpy(name, "spectral_centroid");
+            strcpy(p_name, "Spectral Centroid");
+            strcpy(desc, "Extract the spectral centroid of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral centroid of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_IRREGULARITY_K:
+            strcpy(name, "irregularity_k");
+            strcpy(p_name, "Irregularity I");
+            strcpy(desc, "Extract the irregularity (type I) of a spectrum");
+            strcpy(p_desc,
+                   "Extract the irregularity (type I) of an audio spectrum");
+            strcpy(author, "Krimphoff");
+            *year = 1994;
+            break;
+        case XTRACT_IRREGULARITY_J:
+            strcpy(name, "irregularity_j");
+            strcpy(p_name, "Irregularity II");
+            strcpy(desc, "Extract the irregularity (type II) of a spectrum");
+            strcpy(p_desc,
+                   "Extract the irregularity (type II) of an audio spectrum");
+            strcpy(author, "Jensen");
+            *year = 1999;
+            break;
+        case XTRACT_TRISTIMULUS_1:
+            strcpy(name, "tristimulus_1");
+            strcpy(p_name, "Tristimulus I");
+            strcpy(desc, "Extract the tristimulus (type I) of a spectrum");
+            strcpy(p_desc,
+                   "Extract the tristimulus (type I) of an audio spectrum");
+            strcpy(author, "Pollard and Jansson");
+            *year = 1982;
+            break;
+        case XTRACT_TRISTIMULUS_2:
+            strcpy(name, "tristimulus_2");
+            strcpy(p_name, "Tristimulus II");
+            strcpy(desc, "Extract the tristimulus (type II) of a spectrum");
+            strcpy(p_desc,
+                   "Extract the tristimulus (type II) of an audio spectrum");
+            strcpy(author, "Pollard and Jansson");
+            *year = 1982;
+            break;
+        case XTRACT_TRISTIMULUS_3:
+            strcpy(name, "tristimulus_3");
+            strcpy(p_name, "Tristimulus III");
+            strcpy(desc,
+                   "Extract the tristimulus (type III) of a spectrum");
+            strcpy(p_desc,
+                   "Extract the tristimulus (type III) of an audio spectrum");
+            strcpy(author, "Pollard and Jansson");
+            *year = 1982;
+            break;
+        case XTRACT_SMOOTHNESS:
+            strcpy(name, "smoothness");
+            strcpy(p_name, "Spectral Smoothness");
+            strcpy(desc, "Extract the spectral smoothness of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral smoothness of an audio spectrum");
+            strcpy(author, "McAdams");
+            *year = 1999;
+            break;
+        case XTRACT_FLATNESS:
+            strcpy(name, "flatness");
+            strcpy(p_name, "Spectral Flatness");
+            strcpy(desc, "Extract the spectral flatness of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral flatness of an audio spectrum");
+            strcpy(author, "Tristan Jehan");
+            *year = 2005;
+            break;
+        case XTRACT_FLATNESS_DB:
+            strcpy(name, "flatness_db");
+            strcpy(p_name, "Log Spectral Flatness");
+            strcpy(desc, "Extract the log spectral flatness of a spectrum");
+            strcpy(p_desc,
+                   "Extract the log spectral flatness of an audio spectrum");
+            strcpy(author, "Peeters");
+            *year = 2003;
+            break;
+        case XTRACT_SPREAD:
+            strcpy(name, "spread");
+            strcpy(p_name, "Spectral Spread");
+            strcpy(desc, "Extract the spectral spread of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral spread of an audio spectrum");
+            strcpy(author, "Norman Casagrande");
+            *year = 2005;
+            break;
+        case XTRACT_ZCR:
+            strcpy(name, "zcr");
+            strcpy(p_name, "Zero Crossing Rate");
+            strcpy(desc, "Extract the zero crossing rate of a vector");
+            strcpy(p_desc,
+                   "Extract the zero crossing rate of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_LOUDNESS:
+            strcpy(name, "loudness");
+            strcpy(p_name, "Loudness");
+            strcpy(desc,
+                   "Extract the loudness of a signal from its spectrum");
+            strcpy(p_desc,
+                   "Extract the loudness of an audio signal from its spectrum");
+            strcpy(author, "Moore, Glasberg et al");
+            *year = 2005;
+            break;
+        case XTRACT_HIGHEST_VALUE:
+            strcpy(name, "highest_value");
+            strcpy(p_name, "Highest Value");
+            strcpy(desc, "Extract the highest value from an input vector");
+            strcpy(p_desc, "Extract the highest value from a given range");
+            strcpy(author, "");
+            break;
+        case XTRACT_SUM:
+            strcpy(name, "sum");
+            strcpy(p_name, "Sum of Values");
+            strcpy(desc,
+                   "Extract the sum of the values in an input vector");
+            strcpy(p_desc,
+                   "Extract the sum of the values in a given range");
+            strcpy(author, "");
+            break;
+        case XTRACT_RMS_AMPLITUDE:
+            strcpy(name, "rms_amplitude");
+            strcpy(p_name, "RMS Amplitude");
+            strcpy(desc, "Extract the RMS amplitude of a signal");
+            strcpy(p_desc, "Extract the RMS amplitude of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_POWER:
+            strcpy(name, "power");
+            strcpy(p_name, "Spectral Power");
+            strcpy(desc, "Extract the spectral power of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral power of an audio spectrum");
+            strcpy(author, "Bee Suan Ong");
+            *year = 2005;
+            break;
+        case XTRACT_SHARPNESS:
+            strcpy(name, "sharpness");
+            strcpy(p_name, "Spectral Sharpness");
+            strcpy(desc, "Extract the spectral sharpness of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral sharpness of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_SPECTRAL_SLOPE:
+            strcpy(name, "spectral_slope");
+            strcpy(p_name, "Spectral Slope");
+            strcpy(desc, "Extract the spectral slope of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral slope of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_HPS:
+            strcpy(name, "hps");
+            strcpy(p_name, "Harmonic Product Spectrum");
+            strcpy(desc,
+                   "Extract the harmonic product spectrum of a spectrum");
+            strcpy(p_desc,
+                   "Extract the harmonic product spectrum of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_FLUX:
+            strcpy(name, "flux");
+            strcpy(p_name, "Spectral Flux");
+            strcpy(desc, "Extract the spectral flux of a spectrum");
+            strcpy(p_desc,
+                   "Extract the spectral flux of an audio spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_LNORM:
+            strcpy(name, "lnorm");
+            strcpy(p_name, "L-norm");
+            strcpy(desc, "Extract the L-norm of a vector");
+            strcpy(p_desc, "Extract the L-norm of a vector");
+            strcpy(author, "");
+            break;
+        case XTRACT_ATTACK_TIME:
+            strcpy(name, "attack_time");
+            strcpy(p_name, "Attack Time");
+            strcpy(desc, "Extract the attack time of a signal");
+            strcpy(p_desc, "Extract the attack time of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_DECAY_TIME:
+            strcpy(name, "decay_time");
+            strcpy(p_name, "Decay Time");
+            strcpy(desc, "Extract the decay time of a signal");
+            strcpy(p_desc, "Extract the decay time of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_DIFFERENCE_VECTOR:
+            strcpy(name, "difference_vector");
+            strcpy(p_name, "Difference vector");
+            strcpy(desc, "Extract the difference between two vectors");
+            strcpy(p_desc, "Extract the difference between two vectors");
+            strcpy(author, "");
+            break;
+        case XTRACT_AUTOCORRELATION_FFT:
+            strcpy(name, "autocorrelation_fft");
+            strcpy(p_name, "Autocorrelation (FFT method)");
+            strcpy(desc, "Extract the autocorrelation of a signal (fft method)");
+            strcpy(p_desc, "Extract the autocorrelation of an audio signal (fft method)");
+            strcpy(author, "");
+            break;
+        case XTRACT_DCT:
+            strcpy(name, "dct");
+            strcpy(p_name, "Discrete Cosine Transform");
+            strcpy(desc, "Extract the DCT of a signal");
+            strcpy(p_desc, "Extract the DCT of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_AUTOCORRELATION:
+            strcpy(name, "autocorrelation");
+            strcpy(p_name, "Autocorrelation");
+            strcpy(desc, "Extract the autocorrelation of a signal");
+            strcpy(p_desc,
+                   "Extract the autocorrelation of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_AMDF:
+            strcpy(name, "amdf");
+            strcpy(p_name, "Average Magnitude Difference Function");
+            strcpy(desc, "Extract the AMDF of a signal");
+            strcpy(p_desc, "Extract the AMDF of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_ASDF:
+            strcpy(name, "asdf");
+            strcpy(p_name, "Average Squared Difference Function");
+            strcpy(desc, "Extract the ASDF of a signal");
+            strcpy(p_desc, "Extract the ASDF of an audio signal");
+            strcpy(author, "");
+            break;
+        case XTRACT_NONZERO_COUNT:
+            strcpy(name, "nonzero_count");
+            strcpy(p_name, "Non-zero count");
+            strcpy(desc,
+                   "Extract the number of non-zero elements in the input vector");
+            strcpy(p_desc,
+                   "Extract the number of non-zero elements in an input spectrum");
+            strcpy(author, "");
+            break;
+        case XTRACT_WINDOWED:
+            strcpy(name, "windowed");
+            strcpy(p_name, "Windowed frame");
+            strcpy(desc, "Apply a window function to a frame of data");
+            strcpy(p_desc, "Apply a window function to a frame of data");
+            strcpy(author, "");
+            break;
+        default:
+            strcpy(name, "");
+            strcpy(p_name, "");
+            strcpy(desc, "");
+            strcpy(p_desc, "");
+            strcpy(author, "");
+            break;
         }
 
-        switch(f){
+        switch(f)
+        {
 
-            case XTRACT_VARIANCE:
-            case XTRACT_STANDARD_DEVIATION:
-            case XTRACT_AVERAGE_DEVIATION:
-            case XTRACT_SPECTRAL_VARIANCE:
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+        case XTRACT_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
             /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-            case XTRACT_SPECTRAL_INHARMONICITY:
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-            case XTRACT_FLATNESS_DB:
-            case XTRACT_TONALITY:
-                *argc = 1;
-                *argv_type = XTRACT_FLOAT;
-                break;
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_HARMONIC_SPECTRUM:
-            case XTRACT_NOISINESS:
-            case XTRACT_CREST:
-            case XTRACT_ROLLOFF:
-            case XTRACT_FLUX: 
-            case XTRACT_LNORM: 
-                *argc = 2;
-                *argv_type = XTRACT_FLOAT;
-                break;
-            case XTRACT_SPECTRUM:
-                *argc = 4;
-                *argv_type = XTRACT_FLOAT;
-                break;
-            case XTRACT_SUBBANDS:
-                *argc = 4;
-                *argv_type = XTRACT_INT;
-                break;
-            case XTRACT_MFCC:
-                *argc = 1;
-                *argv_type = XTRACT_MEL_FILTER;
-                break;
-            case XTRACT_LPCC:
-                *argc = 1;
-                *argv_type = XTRACT_INT;
-                break;
-            case XTRACT_BARK_COEFFICIENTS:
-                *argc = XTRACT_BARK_BANDS;
-                *argv_type = XTRACT_INT;
-                break;
-            case XTRACT_WINDOWED:
-                *argc = XTRACT_WINDOW_SIZE;
-                *argv_type = XTRACT_FLOAT;
-                break;
-            case XTRACT_MEAN:
-            case XTRACT_SPECTRAL_MEAN:
-            case XTRACT_SPECTRAL_CENTROID:
-            case XTRACT_IRREGULARITY_K:
-            case XTRACT_IRREGULARITY_J:
-            case XTRACT_TRISTIMULUS_1:
-            case XTRACT_TRISTIMULUS_2:
-            case XTRACT_TRISTIMULUS_3:
-            case XTRACT_SMOOTHNESS:
-            case XTRACT_FLATNESS:
-            case XTRACT_SPREAD:
-            case XTRACT_ZCR:
-            case XTRACT_LOUDNESS:
-            case XTRACT_HIGHEST_VALUE:
-            case XTRACT_SUM:
-            case XTRACT_RMS_AMPLITUDE:
-            case XTRACT_POWER:
-            case XTRACT_SHARPNESS:
-            case XTRACT_SPECTRAL_SLOPE:
-            case XTRACT_HPS:
-            case XTRACT_ATTACK_TIME: 
-            case XTRACT_DECAY_TIME: 
-            case XTRACT_DIFFERENCE_VECTOR: 
-            case XTRACT_AUTOCORRELATION_FFT:
-            case XTRACT_DCT:
-            case XTRACT_AUTOCORRELATION:
-            case XTRACT_AMDF:
-            case XTRACT_ASDF:
-            case XTRACT_NONZERO_COUNT:
-            case XTRACT_ODD_EVEN_RATIO:
-            case XTRACT_LPC:
-            default:
-                *argc = 0;
-                break;
+        case XTRACT_SPECTRAL_INHARMONICITY:
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+        case XTRACT_FLATNESS_DB:
+        case XTRACT_TONALITY:
+            *argc = 1;
+            *argv_type = XTRACT_FLOAT;
+            break;
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_HARMONIC_SPECTRUM:
+        case XTRACT_NOISINESS:
+        case XTRACT_CREST:
+        case XTRACT_ROLLOFF:
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+            *argc = 2;
+            *argv_type = XTRACT_FLOAT;
+            break;
+        case XTRACT_SPECTRUM:
+            *argc = 4;
+            *argv_type = XTRACT_FLOAT;
+            break;
+        case XTRACT_SUBBANDS:
+            *argc = 4;
+            *argv_type = XTRACT_INT;
+            break;
+        case XTRACT_MFCC:
+            *argc = 1;
+            *argv_type = XTRACT_MEL_FILTER;
+            break;
+        case XTRACT_LPCC:
+            *argc = 1;
+            *argv_type = XTRACT_INT;
+            break;
+        case XTRACT_BARK_COEFFICIENTS:
+            *argc = XTRACT_BARK_BANDS;
+            *argv_type = XTRACT_INT;
+            break;
+        case XTRACT_WINDOWED:
+            *argc = XTRACT_WINDOW_SIZE;
+            *argv_type = XTRACT_FLOAT;
+            break;
+        case XTRACT_MEAN:
+        case XTRACT_SPECTRAL_MEAN:
+        case XTRACT_SPECTRAL_CENTROID:
+        case XTRACT_IRREGULARITY_K:
+        case XTRACT_IRREGULARITY_J:
+        case XTRACT_TRISTIMULUS_1:
+        case XTRACT_TRISTIMULUS_2:
+        case XTRACT_TRISTIMULUS_3:
+        case XTRACT_SMOOTHNESS:
+        case XTRACT_FLATNESS:
+        case XTRACT_SPREAD:
+        case XTRACT_ZCR:
+        case XTRACT_LOUDNESS:
+        case XTRACT_HIGHEST_VALUE:
+        case XTRACT_SUM:
+        case XTRACT_RMS_AMPLITUDE:
+        case XTRACT_POWER:
+        case XTRACT_SHARPNESS:
+        case XTRACT_SPECTRAL_SLOPE:
+        case XTRACT_HPS:
+        case XTRACT_ATTACK_TIME:
+        case XTRACT_DECAY_TIME:
+        case XTRACT_DIFFERENCE_VECTOR:
+        case XTRACT_AUTOCORRELATION_FFT:
+        case XTRACT_DCT:
+        case XTRACT_AUTOCORRELATION:
+        case XTRACT_AMDF:
+        case XTRACT_ASDF:
+        case XTRACT_NONZERO_COUNT:
+        case XTRACT_ODD_EVEN_RATIO:
+        case XTRACT_LPC:
+        default:
+            *argc = 0;
+            break;
         }
 
         is_scalar = &d->is_scalar;
 
-        switch(f){
+        switch(f)
+        {
+        case XTRACT_MEAN:
+        case XTRACT_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_SPECTRAL_MEAN:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+            /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_SPECTRAL_CENTROID:
+        case XTRACT_IRREGULARITY_K:
+        case XTRACT_IRREGULARITY_J:
+        case XTRACT_TRISTIMULUS_1:
+        case XTRACT_TRISTIMULUS_2:
+        case XTRACT_TRISTIMULUS_3:
+        case XTRACT_SMOOTHNESS:
+        case XTRACT_SPREAD:
+        case XTRACT_ZCR:
+        case XTRACT_ROLLOFF:
+        case XTRACT_LOUDNESS:
+        case XTRACT_FLATNESS:
+        case XTRACT_FLATNESS_DB:
+        case XTRACT_TONALITY:
+        case XTRACT_CREST:
+        case XTRACT_NOISINESS:
+        case XTRACT_RMS_AMPLITUDE:
+        case XTRACT_SPECTRAL_INHARMONICITY:
+        case XTRACT_POWER:
+        case XTRACT_ODD_EVEN_RATIO:
+        case XTRACT_SHARPNESS:
+        case XTRACT_SPECTRAL_SLOPE:
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_HIGHEST_VALUE:
+        case XTRACT_SUM:
+        case XTRACT_HPS:
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+        case XTRACT_NONZERO_COUNT:
+            *is_scalar = XTRACT_TRUE;
+            break;
+        case XTRACT_AUTOCORRELATION:
+        case XTRACT_AMDF:
+        case XTRACT_ASDF:
+        case XTRACT_BARK_COEFFICIENTS:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_SPECTRUM:
+        case XTRACT_SUBBANDS:
+        case XTRACT_AUTOCORRELATION_FFT:
+        case XTRACT_MFCC:
+        case XTRACT_LPC:
+        case XTRACT_LPCC:
+        case XTRACT_DCT:
+        case XTRACT_HARMONIC_SPECTRUM:
+        case XTRACT_DIFFERENCE_VECTOR:
+        case XTRACT_WINDOWED:
+            *is_scalar = XTRACT_FALSE;
+            break;
+        default:
+            *is_scalar = XTRACT_TRUE;
+            break;
+
+        }
+
+        is_delta = &d->is_delta;
+
+        switch(f)
+        {
+        case XTRACT_FLUX:
+        case XTRACT_LNORM:
+        case XTRACT_DIFFERENCE_VECTOR:
+            *is_delta = XTRACT_TRUE;
+            break;
+        case XTRACT_MEAN:
+        case XTRACT_VARIANCE:
+        case XTRACT_STANDARD_DEVIATION:
+        case XTRACT_AVERAGE_DEVIATION:
+        case XTRACT_SKEWNESS:
+        case XTRACT_KURTOSIS:
+        case XTRACT_SPECTRAL_MEAN:
+        case XTRACT_SPECTRAL_VARIANCE:
+        case XTRACT_SPECTRAL_STANDARD_DEVIATION:
+            /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
+        case XTRACT_SPECTRAL_SKEWNESS:
+        case XTRACT_SPECTRAL_KURTOSIS:
+        case XTRACT_SPECTRAL_CENTROID:
+        case XTRACT_IRREGULARITY_K:
+        case XTRACT_IRREGULARITY_J:
+        case XTRACT_TRISTIMULUS_1:
+        case XTRACT_TRISTIMULUS_2:
+        case XTRACT_TRISTIMULUS_3:
+        case XTRACT_SMOOTHNESS:
+        case XTRACT_SPREAD:
+        case XTRACT_ZCR:
+        case XTRACT_ROLLOFF:
+        case XTRACT_LOUDNESS:
+        case XTRACT_FLATNESS:
+        case XTRACT_FLATNESS_DB:
+        case XTRACT_TONALITY:
+        case XTRACT_CREST:
+        case XTRACT_NOISINESS:
+        case XTRACT_RMS_AMPLITUDE:
+        case XTRACT_SPECTRAL_INHARMONICITY:
+        case XTRACT_POWER:
+        case XTRACT_ODD_EVEN_RATIO:
+        case XTRACT_SHARPNESS:
+        case XTRACT_SPECTRAL_SLOPE:
+        case XTRACT_LOWEST_VALUE:
+        case XTRACT_HIGHEST_VALUE:
+        case XTRACT_SUM:
+        case XTRACT_HPS:
+        case XTRACT_F0:
+        case XTRACT_FAILSAFE_F0:
+        case XTRACT_NONZERO_COUNT:
+        case XTRACT_AUTOCORRELATION:
+        case XTRACT_AMDF:
+        case XTRACT_ASDF:
+        case XTRACT_BARK_COEFFICIENTS:
+        case XTRACT_PEAK_SPECTRUM:
+        case XTRACT_SPECTRUM:
+        case XTRACT_SUBBANDS:
+        case XTRACT_AUTOCORRELATION_FFT:
+        case XTRACT_MFCC:
+        case XTRACT_LPC:
+        case XTRACT_LPCC:
+        case XTRACT_DCT:
+        case XTRACT_HARMONIC_SPECTRUM:
+        case XTRACT_WINDOWED:
+        default:
+            *is_delta = XTRACT_FALSE;
+            break;
+        }
+
+        if(*is_scalar)
+        {
+
+            result_unit = &d->result.scalar.unit;
+            result_min = &d->result.scalar.min;
+            result_max = &d->result.scalar.max;
+
+            switch(f)
+            {
             case XTRACT_MEAN:
             case XTRACT_VARIANCE:
             case XTRACT_STANDARD_DEVIATION:
             case XTRACT_AVERAGE_DEVIATION:
             case XTRACT_SKEWNESS:
             case XTRACT_KURTOSIS:
-            case XTRACT_SPECTRAL_MEAN:
-            case XTRACT_SPECTRAL_VARIANCE:
-            case XTRACT_SPECTRAL_STANDARD_DEVIATION:
-            /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
+            case XTRACT_RMS_AMPLITUDE:
+            case XTRACT_LOWEST_VALUE:
+            case XTRACT_HIGHEST_VALUE:
+            case XTRACT_SUM:
+            case XTRACT_FLUX:
+            case XTRACT_LNORM:
+            case XTRACT_NONZERO_COUNT:
+            case XTRACT_WINDOWED:
+                *result_unit = XTRACT_ANY;
+                *result_min = XTRACT_ANY;
+                *result_max = XTRACT_ANY;
+                break;
             case XTRACT_SPECTRAL_SKEWNESS:
             case XTRACT_SPECTRAL_KURTOSIS:
-            case XTRACT_SPECTRAL_CENTROID:
             case XTRACT_IRREGULARITY_K:
             case XTRACT_IRREGULARITY_J:
             case XTRACT_TRISTIMULUS_1:
             case XTRACT_TRISTIMULUS_2:
             case XTRACT_TRISTIMULUS_3:
+            case XTRACT_NOISINESS:
             case XTRACT_SMOOTHNESS:
-            case XTRACT_SPREAD:
-            case XTRACT_ZCR:
-            case XTRACT_ROLLOFF:
-            case XTRACT_LOUDNESS:
-            case XTRACT_FLATNESS:
-            case XTRACT_FLATNESS_DB:
-            case XTRACT_TONALITY:
-            case XTRACT_CREST:
-            case XTRACT_NOISINESS:
-            case XTRACT_RMS_AMPLITUDE:
-            case XTRACT_SPECTRAL_INHARMONICITY:
-            case XTRACT_POWER:
-            case XTRACT_ODD_EVEN_RATIO:
-            case XTRACT_SHARPNESS:
-            case XTRACT_SPECTRAL_SLOPE:
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_HIGHEST_VALUE:
-            case XTRACT_SUM:
-            case XTRACT_HPS:
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-            case XTRACT_FLUX:
-            case XTRACT_LNORM:
-            case XTRACT_NONZERO_COUNT:
-                *is_scalar = XTRACT_TRUE;
+                *result_unit = XTRACT_NONE;
+                *result_min = XTRACT_ANY; /* FIX: need to check these */
+                *result_max = XTRACT_ANY;
                 break;
-            case XTRACT_AUTOCORRELATION:
-            case XTRACT_AMDF:
-            case XTRACT_ASDF:
-            case XTRACT_BARK_COEFFICIENTS:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_SPECTRUM:
-            case XTRACT_SUBBANDS:
-            case XTRACT_AUTOCORRELATION_FFT:
-            case XTRACT_MFCC:
-            case XTRACT_LPC:
-            case XTRACT_LPCC:
-            case XTRACT_DCT:
-            case XTRACT_HARMONIC_SPECTRUM:
-            case XTRACT_DIFFERENCE_VECTOR: 
-            case XTRACT_WINDOWED:
-                *is_scalar = XTRACT_FALSE;
-                break;
-            default:
-                *is_scalar = XTRACT_TRUE;
-                break;
-
-        }
-
-        is_delta = &d->is_delta;
-
-        switch(f){
-            case XTRACT_FLUX:
-            case XTRACT_LNORM:
-            case XTRACT_DIFFERENCE_VECTOR:
-                *is_delta = XTRACT_TRUE;
-                break;
-            case XTRACT_MEAN:
-            case XTRACT_VARIANCE:
-            case XTRACT_STANDARD_DEVIATION:
-            case XTRACT_AVERAGE_DEVIATION:
-            case XTRACT_SKEWNESS:
-            case XTRACT_KURTOSIS:
             case XTRACT_SPECTRAL_MEAN:
             case XTRACT_SPECTRAL_VARIANCE:
             case XTRACT_SPECTRAL_STANDARD_DEVIATION:
-            /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-            case XTRACT_SPECTRAL_SKEWNESS:
-            case XTRACT_SPECTRAL_KURTOSIS:
+                /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
             case XTRACT_SPECTRAL_CENTROID:
-            case XTRACT_IRREGULARITY_K:
-            case XTRACT_IRREGULARITY_J:
-            case XTRACT_TRISTIMULUS_1:
-            case XTRACT_TRISTIMULUS_2:
-            case XTRACT_TRISTIMULUS_3:
-            case XTRACT_SMOOTHNESS:
             case XTRACT_SPREAD:
+            case XTRACT_F0:
+            case XTRACT_FAILSAFE_F0:
+            case XTRACT_HPS:
+            case XTRACT_ROLLOFF:
+                *result_unit = XTRACT_HERTZ;
+                *result_min = 0.f;
+                *result_max = XTRACT_SR_UPPER_LIMIT / 2;
+                break;
             case XTRACT_ZCR:
-            case XTRACT_ROLLOFF:
+                *result_unit = XTRACT_HERTZ;
+                *result_min = 0.f;
+                *result_max = XTRACT_ANY;
+                break;
+            case XTRACT_ODD_EVEN_RATIO:
+                *result_unit = XTRACT_NONE;
+                *result_min = 0.f;
+                *result_max = 1.f;
+                break;
+            case XTRACT_FLATNESS_DB:
+                *result_unit = XTRACT_DBFS;
+                *result_min = XTRACT_ANY; /* FIX: check this */
+                *result_max = XTRACT_ANY;
+                break;
             case XTRACT_LOUDNESS:
             case XTRACT_FLATNESS:
-            case XTRACT_FLATNESS_DB:
             case XTRACT_TONALITY:
             case XTRACT_CREST:
-            case XTRACT_NOISINESS:
-            case XTRACT_RMS_AMPLITUDE:
             case XTRACT_SPECTRAL_INHARMONICITY:
             case XTRACT_POWER:
-            case XTRACT_ODD_EVEN_RATIO:
             case XTRACT_SHARPNESS:
             case XTRACT_SPECTRAL_SLOPE:
-            case XTRACT_LOWEST_VALUE:
-            case XTRACT_HIGHEST_VALUE:
-            case XTRACT_SUM:
-            case XTRACT_HPS:
-            case XTRACT_F0:
-            case XTRACT_FAILSAFE_F0:
-            case XTRACT_NONZERO_COUNT:
-            case XTRACT_AUTOCORRELATION:
-            case XTRACT_AMDF:
-            case XTRACT_ASDF:
-            case XTRACT_BARK_COEFFICIENTS:
-            case XTRACT_PEAK_SPECTRUM:
-            case XTRACT_SPECTRUM:
-            case XTRACT_SUBBANDS:
-            case XTRACT_AUTOCORRELATION_FFT:
-            case XTRACT_MFCC:
             case XTRACT_LPC:
             case XTRACT_LPCC:
-            case XTRACT_DCT:
-            case XTRACT_HARMONIC_SPECTRUM:
-            case XTRACT_WINDOWED:
             default:
-                *is_delta = XTRACT_FALSE;
+                *result_unit = XTRACT_UNKNOWN;
+                *result_min = XTRACT_UNKNOWN;
+                *result_max = XTRACT_UNKNOWN;
                 break;
-        }
-
-        if(*is_scalar){
-
-            result_unit = &d->result.scalar.unit;
-            result_min = &d->result.scalar.min;
-            result_max = &d->result.scalar.max;
-
-            switch(f){
-                case XTRACT_MEAN:
-                case XTRACT_VARIANCE:
-                case XTRACT_STANDARD_DEVIATION:
-                case XTRACT_AVERAGE_DEVIATION:
-                case XTRACT_SKEWNESS:
-                case XTRACT_KURTOSIS:
-                case XTRACT_RMS_AMPLITUDE:
-                case XTRACT_LOWEST_VALUE:
-                case XTRACT_HIGHEST_VALUE:
-                case XTRACT_SUM:
-                case XTRACT_FLUX:
-                case XTRACT_LNORM:
-                case XTRACT_NONZERO_COUNT: 
-                case XTRACT_WINDOWED:
-                    *result_unit = XTRACT_ANY;
-                    *result_min = XTRACT_ANY;
-                    *result_max = XTRACT_ANY;
-                    break;
-                case XTRACT_SPECTRAL_SKEWNESS:
-                case XTRACT_SPECTRAL_KURTOSIS:
-                case XTRACT_IRREGULARITY_K:
-                case XTRACT_IRREGULARITY_J:
-                case XTRACT_TRISTIMULUS_1:
-                case XTRACT_TRISTIMULUS_2:
-                case XTRACT_TRISTIMULUS_3:
-                case XTRACT_NOISINESS:
-                case XTRACT_SMOOTHNESS:
-                    *result_unit = XTRACT_NONE;
-                    *result_min = XTRACT_ANY; /* FIX: need to check these */
-                    *result_max = XTRACT_ANY;
-                    break;
-                case XTRACT_SPECTRAL_MEAN:
-                case XTRACT_SPECTRAL_VARIANCE:
-                case XTRACT_SPECTRAL_STANDARD_DEVIATION:
-                /* case XTRACT_SPECTRAL_AVERAGE_DEVIATION: */
-                case XTRACT_SPECTRAL_CENTROID:
-                case XTRACT_SPREAD:
-                case XTRACT_F0:
-                case XTRACT_FAILSAFE_F0:
-                case XTRACT_HPS:
-                case XTRACT_ROLLOFF:
-                    *result_unit = XTRACT_HERTZ;
-                    *result_min = 0.f;
-                    *result_max = XTRACT_SR_UPPER_LIMIT / 2;
-                    break;
-                case XTRACT_ZCR:
-                    *result_unit = XTRACT_HERTZ;
-                    *result_min = 0.f;
-                    *result_max = XTRACT_ANY;
-                    break;
-                case XTRACT_ODD_EVEN_RATIO:
-                    *result_unit = XTRACT_NONE;
-                    *result_min = 0.f;
-                    *result_max = 1.f; 
-                    break;
-                case XTRACT_FLATNESS_DB:
-                    *result_unit = XTRACT_DBFS;
-                    *result_min = XTRACT_ANY; /* FIX: check this */
-                    *result_max = XTRACT_ANY; 
-                    break;
-                case XTRACT_LOUDNESS:
-                case XTRACT_FLATNESS:
-                case XTRACT_TONALITY:
-                case XTRACT_CREST:
-                case XTRACT_SPECTRAL_INHARMONICITY:
-                case XTRACT_POWER:
-                case XTRACT_SHARPNESS:
-                case XTRACT_SPECTRAL_SLOPE:
-                case XTRACT_LPC:
-                case XTRACT_LPCC:
-                default:
-                    *result_unit = XTRACT_UNKNOWN;
-                    *result_min = XTRACT_UNKNOWN;
-                    *result_max = XTRACT_UNKNOWN; 
-                    break;
             }
         }
-        else {
+        else
+        {
 
             result_min = NULL;
             result_max = NULL;
             result_unit = &d->result.vector.unit;
             result_format = &d->result.vector.format;
 
-            switch(f) {
-                case XTRACT_AUTOCORRELATION:
-                case XTRACT_AMDF:
-                case XTRACT_ASDF:
-                case XTRACT_DCT:
-                case XTRACT_SUBBANDS:
-                case XTRACT_WINDOWED:
-                    *result_format = XTRACT_ARBITRARY_SERIES;
-                    *result_unit = XTRACT_ANY;
-                    break;
-                case XTRACT_BARK_COEFFICIENTS:
-                    *result_format = XTRACT_BARK_COEFFS;
-                    *result_unit = XTRACT_UNKNOWN; /* FIX: check */
-                    break;
-                case XTRACT_PEAK_SPECTRUM:
-                case XTRACT_SPECTRUM:
-                case XTRACT_HARMONIC_SPECTRUM:
-                    *result_format = XTRACT_SPECTRAL;
-                    *result_unit = XTRACT_ANY_AMPLITUDE_HERTZ;
-                    break;
-                case XTRACT_AUTOCORRELATION_FFT:
-                    break;
-                case XTRACT_MFCC:
-                    *result_format = XTRACT_MEL_COEFFS;
-                    *result_unit = XTRACT_UNKNOWN; /* FIX: check */
-                    break;
-                case XTRACT_LPC:
-                    *result_format = XTRACT_LPC_COEFFS;
-                    *result_unit = XTRACT_UNKNOWN;
-                    break;
-                case XTRACT_LPCC:
-                    *result_format = XTRACT_LPCC_COEFFS;
-                    *result_unit = XTRACT_UNKNOWN;
-                    break;
-                default:
-                    break;
+            switch(f)
+            {
+            case XTRACT_AUTOCORRELATION:
+            case XTRACT_AMDF:
+            case XTRACT_ASDF:
+            case XTRACT_DCT:
+            case XTRACT_SUBBANDS:
+            case XTRACT_WINDOWED:
+                *result_format = XTRACT_ARBITRARY_SERIES;
+                *result_unit = XTRACT_ANY;
+                break;
+            case XTRACT_BARK_COEFFICIENTS:
+                *result_format = XTRACT_BARK_COEFFS;
+                *result_unit = XTRACT_UNKNOWN; /* FIX: check */
+                break;
+            case XTRACT_PEAK_SPECTRUM:
+            case XTRACT_SPECTRUM:
+            case XTRACT_HARMONIC_SPECTRUM:
+                *result_format = XTRACT_SPECTRAL;
+                *result_unit = XTRACT_ANY_AMPLITUDE_HERTZ;
+                break;
+            case XTRACT_AUTOCORRELATION_FFT:
+                break;
+            case XTRACT_MFCC:
+                *result_format = XTRACT_MEL_COEFFS;
+                *result_unit = XTRACT_UNKNOWN; /* FIX: check */
+                break;
+            case XTRACT_LPC:
+                *result_format = XTRACT_LPC_COEFFS;
+                *result_unit = XTRACT_UNKNOWN;
+                break;
+            case XTRACT_LPCC:
+                *result_format = XTRACT_LPCC_COEFFS;
+                *result_unit = XTRACT_UNKNOWN;
+                break;
+            default:
+                break;
             }
         }
     }
@@ -1321,9 +1335,11 @@
     return fd;
 }
 
-int xtract_free_descriptors(xtract_function_descriptor_t *fd){
+int xtract_free_descriptors(xtract_function_descriptor_t *fd)
+{
 
-    if (fd != NULL) {
+    if (fd != NULL)
+    {
         free(fd);
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fftsg.c	Mon Jan 07 16:27:15 2013 +0000
@@ -0,0 +1,3492 @@
+/*
+Fast Fourier/Cosine/Sine Transform
+    dimension   :one
+    data length :power of 2
+    decimation  :frequency
+    radix       :split-radix
+    data        :inplace
+    table       :use
+functions
+    cdft: Complex Discrete Fourier Transform
+    rdft: Real Discrete Fourier Transform
+    ddct: Discrete Cosine Transform
+    ddst: Discrete Sine Transform
+    dfct: Cosine Transform of RDFT (Real Symmetric DFT)
+    dfst: Sine Transform of RDFT (Real Anti-symmetric DFT)
+function prototypes
+    void cdft(int, int, double *, int *, double *);
+    void rdft(int, int, double *, int *, double *);
+    void ddct(int, int, double *, int *, double *);
+    void ddst(int, int, double *, int *, double *);
+    void dfct(int, double *, double *, int *, double *);
+    void dfst(int, double *, double *, int *, double *);
+macro definitions
+    USE_CDFT_PTHREADS : default=not defined
+        CDFT_THREADS_BEGIN_N  : must be >= 512, default=8192
+        CDFT_4THREADS_BEGIN_N : must be >= 512, default=65536
+    USE_CDFT_WINTHREADS : default=not defined
+        CDFT_THREADS_BEGIN_N  : must be >= 512, default=32768
+        CDFT_4THREADS_BEGIN_N : must be >= 512, default=524288
+
+
+-------- Complex DFT (Discrete Fourier Transform) --------
+    [definition]
+        <case1>
+            X[k] = sum_j=0^n-1 x[j]*exp(2*pi*i*j*k/n), 0<=k<n
+        <case2>
+            X[k] = sum_j=0^n-1 x[j]*exp(-2*pi*i*j*k/n), 0<=k<n
+        (notes: sum_j=0^n-1 is a summation from j=0 to n-1)
+    [usage]
+        <case1>
+            ip[0] = 0; // first time only
+            cdft(2*n, 1, a, ip, w);
+        <case2>
+            ip[0] = 0; // first time only
+            cdft(2*n, -1, a, ip, w);
+    [parameters]
+        2*n            :data length (int)
+                        n >= 1, n = power of 2
+        a[0...2*n-1]   :input/output data (double *)
+                        input data
+                            a[2*j] = Re(x[j]),
+                            a[2*j+1] = Im(x[j]), 0<=j<n
+                        output data
+                            a[2*k] = Re(X[k]),
+                            a[2*k+1] = Im(X[k]), 0<=k<n
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n/2-1]   :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            cdft(2*n, -1, a, ip, w);
+        is
+            cdft(2*n, 1, a, ip, w);
+            for (j = 0; j <= 2 * n - 1; j++) {
+                a[j] *= 1.0 / n;
+            }
+        .
+
+
+-------- Real DFT / Inverse of Real DFT --------
+    [definition]
+        <case1> RDFT
+            R[k] = sum_j=0^n-1 a[j]*cos(2*pi*j*k/n), 0<=k<=n/2
+            I[k] = sum_j=0^n-1 a[j]*sin(2*pi*j*k/n), 0<k<n/2
+        <case2> IRDFT (excluding scale)
+            a[k] = (R[0] + R[n/2]*cos(pi*k))/2 +
+                   sum_j=1^n/2-1 R[j]*cos(2*pi*j*k/n) +
+                   sum_j=1^n/2-1 I[j]*sin(2*pi*j*k/n), 0<=k<n
+    [usage]
+        <case1>
+            ip[0] = 0; // first time only
+            rdft(n, 1, a, ip, w);
+        <case2>
+            ip[0] = 0; // first time only
+            rdft(n, -1, a, ip, w);
+    [parameters]
+        n              :data length (int)
+                        n >= 2, n = power of 2
+        a[0...n-1]     :input/output data (double *)
+                        <case1>
+                            output data
+                                a[2*k] = R[k], 0<=k<n/2
+                                a[2*k+1] = I[k], 0<k<n/2
+                                a[1] = R[n/2]
+                        <case2>
+                            input data
+                                a[2*j] = R[j], 0<=j<n/2
+                                a[2*j+1] = I[j], 0<j<n/2
+                                a[1] = R[n/2]
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n/2)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n/2-1]   :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            rdft(n, 1, a, ip, w);
+        is
+            rdft(n, -1, a, ip, w);
+            for (j = 0; j <= n - 1; j++) {
+                a[j] *= 2.0 / n;
+            }
+        .
+
+
+-------- DCT (Discrete Cosine Transform) / Inverse of DCT --------
+    [definition]
+        <case1> IDCT (excluding scale)
+            C[k] = sum_j=0^n-1 a[j]*cos(pi*j*(k+1/2)/n), 0<=k<n
+        <case2> DCT
+            C[k] = sum_j=0^n-1 a[j]*cos(pi*(j+1/2)*k/n), 0<=k<n
+    [usage]
+        <case1>
+            ip[0] = 0; // first time only
+            ddct(n, 1, a, ip, w);
+        <case2>
+            ip[0] = 0; // first time only
+            ddct(n, -1, a, ip, w);
+    [parameters]
+        n              :data length (int)
+                        n >= 2, n = power of 2
+        a[0...n-1]     :input/output data (double *)
+                        output data
+                            a[k] = C[k], 0<=k<n
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n/2)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n*5/4-1] :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            ddct(n, -1, a, ip, w);
+        is
+            a[0] *= 0.5;
+            ddct(n, 1, a, ip, w);
+            for (j = 0; j <= n - 1; j++) {
+                a[j] *= 2.0 / n;
+            }
+        .
+
+
+-------- DST (Discrete Sine Transform) / Inverse of DST --------
+    [definition]
+        <case1> IDST (excluding scale)
+            S[k] = sum_j=1^n A[j]*sin(pi*j*(k+1/2)/n), 0<=k<n
+        <case2> DST
+            S[k] = sum_j=0^n-1 a[j]*sin(pi*(j+1/2)*k/n), 0<k<=n
+    [usage]
+        <case1>
+            ip[0] = 0; // first time only
+            ddst(n, 1, a, ip, w);
+        <case2>
+            ip[0] = 0; // first time only
+            ddst(n, -1, a, ip, w);
+    [parameters]
+        n              :data length (int)
+                        n >= 2, n = power of 2
+        a[0...n-1]     :input/output data (double *)
+                        <case1>
+                            input data
+                                a[j] = A[j], 0<j<n
+                                a[0] = A[n]
+                            output data
+                                a[k] = S[k], 0<=k<n
+                        <case2>
+                            output data
+                                a[k] = S[k], 0<k<n
+                                a[0] = S[n]
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n/2)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n/2+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n*5/4-1] :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            ddst(n, -1, a, ip, w);
+        is
+            a[0] *= 0.5;
+            ddst(n, 1, a, ip, w);
+            for (j = 0; j <= n - 1; j++) {
+                a[j] *= 2.0 / n;
+            }
+        .
+
+
+-------- Cosine Transform of RDFT (Real Symmetric DFT) --------
+    [definition]
+        C[k] = sum_j=0^n a[j]*cos(pi*j*k/n), 0<=k<=n
+    [usage]
+        ip[0] = 0; // first time only
+        dfct(n, a, t, ip, w);
+    [parameters]
+        n              :data length - 1 (int)
+                        n >= 2, n = power of 2
+        a[0...n]       :input/output data (double *)
+                        output data
+                            a[k] = C[k], 0<=k<=n
+        t[0...n/2]     :work area (double *)
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n/4)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n*5/8-1] :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            a[0] *= 0.5;
+            a[n] *= 0.5;
+            dfct(n, a, t, ip, w);
+        is
+            a[0] *= 0.5;
+            a[n] *= 0.5;
+            dfct(n, a, t, ip, w);
+            for (j = 0; j <= n; j++) {
+                a[j] *= 2.0 / n;
+            }
+        .
+
+
+-------- Sine Transform of RDFT (Real Anti-symmetric DFT) --------
+    [definition]
+        S[k] = sum_j=1^n-1 a[j]*sin(pi*j*k/n), 0<k<n
+    [usage]
+        ip[0] = 0; // first time only
+        dfst(n, a, t, ip, w);
+    [parameters]
+        n              :data length + 1 (int)
+                        n >= 2, n = power of 2
+        a[0...n-1]     :input/output data (double *)
+                        output data
+                            a[k] = S[k], 0<k<n
+                        (a[0] is used for work area)
+        t[0...n/2-1]   :work area (double *)
+        ip[0...*]      :work area for bit reversal (int *)
+                        length of ip >= 2+sqrt(n/4)
+                        strictly,
+                        length of ip >=
+                            2+(1<<(int)(log(n/4+0.5)/log(2))/2).
+                        ip[0],ip[1] are pointers of the cos/sin table.
+        w[0...n*5/8-1] :cos/sin table (double *)
+                        w[],ip[] are initialized if ip[0] == 0.
+    [remark]
+        Inverse of
+            dfst(n, a, t, ip, w);
+        is
+            dfst(n, a, t, ip, w);
+            for (j = 1; j <= n - 1; j++) {
+                a[j] *= 2.0 / n;
+            }
+        .
+
+
+Appendix :
+    The cos/sin table is recalculated when the larger table required.
+    w[] and ip[] are compatible with all routines.
+*/
+
+
+void cdft(int n, int isgn, double *a, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void cftbsub(int n, double *a, int *ip, int nw, double *w);
+    int nw;
+
+    nw = ip[0];
+    if (n > (nw << 2))
+    {
+        nw = n >> 2;
+        makewt(nw, ip, w);
+    }
+    if (isgn >= 0)
+    {
+        cftfsub(n, a, ip, nw, w);
+    }
+    else
+    {
+        cftbsub(n, a, ip, nw, w);
+    }
+}
+
+
+void rdft(int n, int isgn, double *a, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void makect(int nc, int *ip, double *c);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void cftbsub(int n, double *a, int *ip, int nw, double *w);
+    void rftfsub(int n, double *a, int nc, double *c);
+    void rftbsub(int n, double *a, int nc, double *c);
+    int nw, nc;
+    double xi;
+
+    nw = ip[0];
+    if (n > (nw << 2))
+    {
+        nw = n >> 2;
+        makewt(nw, ip, w);
+    }
+    nc = ip[1];
+    if (n > (nc << 2))
+    {
+        nc = n >> 2;
+        makect(nc, ip, w + nw);
+    }
+    if (isgn >= 0)
+    {
+        if (n > 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+            rftfsub(n, a, nc, w + nw);
+        }
+        else if (n == 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+        }
+        xi = a[0] - a[1];
+        a[0] += a[1];
+        a[1] = xi;
+    }
+    else
+    {
+        a[1] = 0.5 * (a[0] - a[1]);
+        a[0] -= a[1];
+        if (n > 4)
+        {
+            rftbsub(n, a, nc, w + nw);
+            cftbsub(n, a, ip, nw, w);
+        }
+        else if (n == 4)
+        {
+            cftbsub(n, a, ip, nw, w);
+        }
+    }
+}
+
+
+void ddct(int n, int isgn, double *a, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void makect(int nc, int *ip, double *c);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void cftbsub(int n, double *a, int *ip, int nw, double *w);
+    void rftfsub(int n, double *a, int nc, double *c);
+    void rftbsub(int n, double *a, int nc, double *c);
+    void dctsub(int n, double *a, int nc, double *c);
+    int j, nw, nc;
+    double xr;
+
+    nw = ip[0];
+    if (n > (nw << 2))
+    {
+        nw = n >> 2;
+        makewt(nw, ip, w);
+    }
+    nc = ip[1];
+    if (n > nc)
+    {
+        nc = n;
+        makect(nc, ip, w + nw);
+    }
+    if (isgn < 0)
+    {
+        xr = a[n - 1];
+        for (j = n - 2; j >= 2; j -= 2)
+        {
+            a[j + 1] = a[j] - a[j - 1];
+            a[j] += a[j - 1];
+        }
+        a[1] = a[0] - xr;
+        a[0] += xr;
+        if (n > 4)
+        {
+            rftbsub(n, a, nc, w + nw);
+            cftbsub(n, a, ip, nw, w);
+        }
+        else if (n == 4)
+        {
+            cftbsub(n, a, ip, nw, w);
+        }
+    }
+    dctsub(n, a, nc, w + nw);
+    if (isgn >= 0)
+    {
+        if (n > 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+            rftfsub(n, a, nc, w + nw);
+        }
+        else if (n == 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+        }
+        xr = a[0] - a[1];
+        a[0] += a[1];
+        for (j = 2; j < n; j += 2)
+        {
+            a[j - 1] = a[j] - a[j + 1];
+            a[j] += a[j + 1];
+        }
+        a[n - 1] = xr;
+    }
+}
+
+
+void ddst(int n, int isgn, double *a, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void makect(int nc, int *ip, double *c);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void cftbsub(int n, double *a, int *ip, int nw, double *w);
+    void rftfsub(int n, double *a, int nc, double *c);
+    void rftbsub(int n, double *a, int nc, double *c);
+    void dstsub(int n, double *a, int nc, double *c);
+    int j, nw, nc;
+    double xr;
+
+    nw = ip[0];
+    if (n > (nw << 2))
+    {
+        nw = n >> 2;
+        makewt(nw, ip, w);
+    }
+    nc = ip[1];
+    if (n > nc)
+    {
+        nc = n;
+        makect(nc, ip, w + nw);
+    }
+    if (isgn < 0)
+    {
+        xr = a[n - 1];
+        for (j = n - 2; j >= 2; j -= 2)
+        {
+            a[j + 1] = -a[j] - a[j - 1];
+            a[j] -= a[j - 1];
+        }
+        a[1] = a[0] + xr;
+        a[0] -= xr;
+        if (n > 4)
+        {
+            rftbsub(n, a, nc, w + nw);
+            cftbsub(n, a, ip, nw, w);
+        }
+        else if (n == 4)
+        {
+            cftbsub(n, a, ip, nw, w);
+        }
+    }
+    dstsub(n, a, nc, w + nw);
+    if (isgn >= 0)
+    {
+        if (n > 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+            rftfsub(n, a, nc, w + nw);
+        }
+        else if (n == 4)
+        {
+            cftfsub(n, a, ip, nw, w);
+        }
+        xr = a[0] - a[1];
+        a[0] += a[1];
+        for (j = 2; j < n; j += 2)
+        {
+            a[j - 1] = -a[j] - a[j + 1];
+            a[j] -= a[j + 1];
+        }
+        a[n - 1] = -xr;
+    }
+}
+
+
+void dfct(int n, double *a, double *t, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void makect(int nc, int *ip, double *c);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void rftfsub(int n, double *a, int nc, double *c);
+    void dctsub(int n, double *a, int nc, double *c);
+    int j, k, l, m, mh, nw, nc;
+    double xr, xi, yr, yi;
+
+    nw = ip[0];
+    if (n > (nw << 3))
+    {
+        nw = n >> 3;
+        makewt(nw, ip, w);
+    }
+    nc = ip[1];
+    if (n > (nc << 1))
+    {
+        nc = n >> 1;
+        makect(nc, ip, w + nw);
+    }
+    m = n >> 1;
+    yi = a[m];
+    xi = a[0] + a[n];
+    a[0] -= a[n];
+    t[0] = xi - yi;
+    t[m] = xi + yi;
+    if (n > 2)
+    {
+        mh = m >> 1;
+        for (j = 1; j < mh; j++)
+        {
+            k = m - j;
+            xr = a[j] - a[n - j];
+            xi = a[j] + a[n - j];
+            yr = a[k] - a[n - k];
+            yi = a[k] + a[n - k];
+            a[j] = xr;
+            a[k] = yr;
+            t[j] = xi - yi;
+            t[k] = xi + yi;
+        }
+        t[mh] = a[mh] + a[n - mh];
+        a[mh] -= a[n - mh];
+        dctsub(m, a, nc, w + nw);
+        if (m > 4)
+        {
+            cftfsub(m, a, ip, nw, w);
+            rftfsub(m, a, nc, w + nw);
+        }
+        else if (m == 4)
+        {
+            cftfsub(m, a, ip, nw, w);
+        }
+        a[n - 1] = a[0] - a[1];
+        a[1] = a[0] + a[1];
+        for (j = m - 2; j >= 2; j -= 2)
+        {
+            a[2 * j + 1] = a[j] + a[j + 1];
+            a[2 * j - 1] = a[j] - a[j + 1];
+        }
+        l = 2;
+        m = mh;
+        while (m >= 2)
+        {
+            dctsub(m, t, nc, w + nw);
+            if (m > 4)
+            {
+                cftfsub(m, t, ip, nw, w);
+                rftfsub(m, t, nc, w + nw);
+            }
+            else if (m == 4)
+            {
+                cftfsub(m, t, ip, nw, w);
+            }
+            a[n - l] = t[0] - t[1];
+            a[l] = t[0] + t[1];
+            k = 0;
+            for (j = 2; j < m; j += 2)
+            {
+                k += l << 2;
+                a[k - l] = t[j] - t[j + 1];
+                a[k + l] = t[j] + t[j + 1];
+            }
+            l <<= 1;
+            mh = m >> 1;
+            for (j = 0; j < mh; j++)
+            {
+                k = m - j;
+                t[j] = t[m + k] - t[m + j];
+                t[k] = t[m + k] + t[m + j];
+            }
+            t[mh] = t[m + mh];
+            m = mh;
+        }
+        a[l] = t[0];
+        a[n] = t[2] - t[1];
+        a[0] = t[2] + t[1];
+    }
+    else
+    {
+        a[1] = a[0];
+        a[2] = t[0];
+        a[0] = t[1];
+    }
+}
+
+
+void dfst(int n, double *a, double *t, int *ip, double *w)
+{
+    void makewt(int nw, int *ip, double *w);
+    void makect(int nc, int *ip, double *c);
+    void cftfsub(int n, double *a, int *ip, int nw, double *w);
+    void rftfsub(int n, double *a, int nc, double *c);
+    void dstsub(int n, double *a, int nc, double *c);
+    int j, k, l, m, mh, nw, nc;
+    double xr, xi, yr, yi;
+
+    nw = ip[0];
+    if (n > (nw << 3))
+    {
+        nw = n >> 3;
+        makewt(nw, ip, w);
+    }
+    nc = ip[1];
+    if (n > (nc << 1))
+    {
+        nc = n >> 1;
+        makect(nc, ip, w + nw);
+    }
+    if (n > 2)
+    {
+        m = n >> 1;
+        mh = m >> 1;
+        for (j = 1; j < mh; j++)
+        {
+            k = m - j;
+            xr = a[j] + a[n - j];
+            xi = a[j] - a[n - j];
+            yr = a[k] + a[n - k];
+            yi = a[k] - a[n - k];
+            a[j] = xr;
+            a[k] = yr;
+            t[j] = xi + yi;
+            t[k] = xi - yi;
+        }
+        t[0] = a[mh] - a[n - mh];
+        a[mh] += a[n - mh];
+        a[0] = a[m];
+        dstsub(m, a, nc, w + nw);
+        if (m > 4)
+        {
+            cftfsub(m, a, ip, nw, w);
+            rftfsub(m, a, nc, w + nw);
+        }
+        else if (m == 4)
+        {
+            cftfsub(m, a, ip, nw, w);
+        }
+        a[n - 1] = a[1] - a[0];
+        a[1] = a[0] + a[1];
+        for (j = m - 2; j >= 2; j -= 2)
+        {
+            a[2 * j + 1] = a[j] - a[j + 1];
+            a[2 * j - 1] = -a[j] - a[j + 1];
+        }
+        l = 2;
+        m = mh;
+        while (m >= 2)
+        {
+            dstsub(m, t, nc, w + nw);
+            if (m > 4)
+            {
+                cftfsub(m, t, ip, nw, w);
+                rftfsub(m, t, nc, w + nw);
+            }
+            else if (m == 4)
+            {
+                cftfsub(m, t, ip, nw, w);
+            }
+            a[n - l] = t[1] - t[0];
+            a[l] = t[0] + t[1];
+            k = 0;
+            for (j = 2; j < m; j += 2)
+            {
+                k += l << 2;
+                a[k - l] = -t[j] - t[j + 1];
+                a[k + l] = t[j] - t[j + 1];
+            }
+            l <<= 1;
+            mh = m >> 1;
+            for (j = 1; j < mh; j++)
+            {
+                k = m - j;
+                t[j] = t[m + k] + t[m + j];
+                t[k] = t[m + k] - t[m + j];
+            }
+            t[0] = t[m + mh];
+            m = mh;
+        }
+        a[l] = t[0];
+    }
+    a[0] = 0;
+}
+
+
+/* -------- initializing routines -------- */
+
+
+#include <math.h>
+
+void makewt(int nw, int *ip, double *w)
+{
+    void makeipt(int nw, int *ip);
+    int j, nwh, nw0, nw1;
+    double delta, wn4r, wk1r, wk1i, wk3r, wk3i;
+
+    ip[0] = nw;
+    ip[1] = 1;
+    if (nw > 2)
+    {
+        nwh = nw >> 1;
+        delta = atan(1.0) / nwh;
+        wn4r = cos(delta * nwh);
+        w[0] = 1;
+        w[1] = wn4r;
+        if (nwh == 4)
+        {
+            w[2] = cos(delta * 2);
+            w[3] = sin(delta * 2);
+        }
+        else if (nwh > 4)
+        {
+            makeipt(nw, ip);
+            w[2] = 0.5 / cos(delta * 2);
+            w[3] = 0.5 / cos(delta * 6);
+            for (j = 4; j < nwh; j += 4)
+            {
+                w[j] = cos(delta * j);
+                w[j + 1] = sin(delta * j);
+                w[j + 2] = cos(3 * delta * j);
+                w[j + 3] = -sin(3 * delta * j);
+            }
+        }
+        nw0 = 0;
+        while (nwh > 2)
+        {
+            nw1 = nw0 + nwh;
+            nwh >>= 1;
+            w[nw1] = 1;
+            w[nw1 + 1] = wn4r;
+            if (nwh == 4)
+            {
+                wk1r = w[nw0 + 4];
+                wk1i = w[nw0 + 5];
+                w[nw1 + 2] = wk1r;
+                w[nw1 + 3] = wk1i;
+            }
+            else if (nwh > 4)
+            {
+                wk1r = w[nw0 + 4];
+                wk3r = w[nw0 + 6];
+                w[nw1 + 2] = 0.5 / wk1r;
+                w[nw1 + 3] = 0.5 / wk3r;
+                for (j = 4; j < nwh; j += 4)
+                {
+                    wk1r = w[nw0 + 2 * j];
+                    wk1i = w[nw0 + 2 * j + 1];
+                    wk3r = w[nw0 + 2 * j + 2];
+                    wk3i = w[nw0 + 2 * j + 3];
+                    w[nw1 + j] = wk1r;
+                    w[nw1 + j + 1] = wk1i;
+                    w[nw1 + j + 2] = wk3r;
+                    w[nw1 + j + 3] = wk3i;
+                }
+            }
+            nw0 = nw1;
+        }
+    }
+}
+
+
+void makeipt(int nw, int *ip)
+{
+    int j, l, m, m2, p, q;
+
+    ip[2] = 0;
+    ip[3] = 16;
+    m = 2;
+    for (l = nw; l > 32; l >>= 2)
+    {
+        m2 = m << 1;
+        q = m2 << 3;
+        for (j = m; j < m2; j++)
+        {
+            p = ip[j] << 2;
+            ip[m + j] = p;
+            ip[m2 + j] = p + q;
+        }
+        m = m2;
+    }
+}
+
+
+void makect(int nc, int *ip, double *c)
+{
+    int j, nch;
+    double delta;
+
+    ip[1] = nc;
+    if (nc > 1)
+    {
+        nch = nc >> 1;
+        delta = atan(1.0) / nch;
+        c[0] = cos(delta * nch);
+        c[nch] = 0.5 * c[0];
+        for (j = 1; j < nch; j++)
+        {
+            c[j] = 0.5 * cos(delta * j);
+            c[nc - j] = 0.5 * sin(delta * j);
+        }
+    }
+}
+
+
+/* -------- child routines -------- */
+
+
+#ifdef USE_CDFT_PTHREADS
+#define USE_CDFT_THREADS
+#ifndef CDFT_THREADS_BEGIN_N
+#define CDFT_THREADS_BEGIN_N 8192
+#endif
+#ifndef CDFT_4THREADS_BEGIN_N
+#define CDFT_4THREADS_BEGIN_N 65536
+#endif
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define cdft_thread_t pthread_t
+#define cdft_thread_create(thp,func,argp) { \
+    if (pthread_create(thp, NULL, func, (void *) argp) != 0) { \
+        fprintf(stderr, "cdft thread error\n"); \
+        exit(1); \
+    } \
+}
+#define cdft_thread_wait(th) { \
+    if (pthread_join(th, NULL) != 0) { \
+        fprintf(stderr, "cdft thread error\n"); \
+        exit(1); \
+    } \
+}
+#endif /* USE_CDFT_PTHREADS */
+
+
+#ifdef USE_CDFT_WINTHREADS
+#define USE_CDFT_THREADS
+#ifndef CDFT_THREADS_BEGIN_N
+#define CDFT_THREADS_BEGIN_N 32768
+#endif
+#ifndef CDFT_4THREADS_BEGIN_N
+#define CDFT_4THREADS_BEGIN_N 524288
+#endif
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#define cdft_thread_t HANDLE
+#define cdft_thread_create(thp,func,argp) { \
+    DWORD thid; \
+    *(thp) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) func, (LPVOID) argp, 0, &thid); \
+    if (*(thp) == 0) { \
+        fprintf(stderr, "cdft thread error\n"); \
+        exit(1); \
+    } \
+}
+#define cdft_thread_wait(th) { \
+    WaitForSingleObject(th, INFINITE); \
+    CloseHandle(th); \
+}
+#endif /* USE_CDFT_WINTHREADS */
+
+
+void cftfsub(int n, double *a, int *ip, int nw, double *w)
+{
+    void bitrv2(int n, int *ip, double *a);
+    void bitrv216(double *a);
+    void bitrv208(double *a);
+    void cftf1st(int n, double *a, double *w);
+    void cftrec4(int n, double *a, int nw, double *w);
+    void cftleaf(int n, int isplt, double *a, int nw, double *w);
+    void cftfx41(int n, double *a, int nw, double *w);
+    void cftf161(double *a, double *w);
+    void cftf081(double *a, double *w);
+    void cftf040(double *a);
+    void cftx020(double *a);
+#ifdef USE_CDFT_THREADS
+    void cftrec4_th(int n, double *a, int nw, double *w);
+#endif /* USE_CDFT_THREADS */
+
+    if (n > 8)
+    {
+        if (n > 32)
+        {
+            cftf1st(n, a, &w[nw - (n >> 2)]);
+#ifdef USE_CDFT_THREADS
+            if (n > CDFT_THREADS_BEGIN_N)
+            {
+                cftrec4_th(n, a, nw, w);
+            }
+            else
+#endif /* USE_CDFT_THREADS */
+                if (n > 512)
+                {
+                    cftrec4(n, a, nw, w);
+                }
+                else if (n > 128)
+                {
+                    cftleaf(n, 1, a, nw, w);
+                }
+                else
+                {
+                    cftfx41(n, a, nw, w);
+                }
+            bitrv2(n, ip, a);
+        }
+        else if (n == 32)
+        {
+            cftf161(a, &w[nw - 8]);
+            bitrv216(a);
+        }
+        else
+        {
+            cftf081(a, w);
+            bitrv208(a);
+        }
+    }
+    else if (n == 8)
+    {
+        cftf040(a);
+    }
+    else if (n == 4)
+    {
+        cftx020(a);
+    }
+}
+
+
+void cftbsub(int n, double *a, int *ip, int nw, double *w)
+{
+    void bitrv2conj(int n, int *ip, double *a);
+    void bitrv216neg(double *a);
+    void bitrv208neg(double *a);
+    void cftb1st(int n, double *a, double *w);
+    void cftrec4(int n, double *a, int nw, double *w);
+    void cftleaf(int n, int isplt, double *a, int nw, double *w);
+    void cftfx41(int n, double *a, int nw, double *w);
+    void cftf161(double *a, double *w);
+    void cftf081(double *a, double *w);
+    void cftb040(double *a);
+    void cftx020(double *a);
+#ifdef USE_CDFT_THREADS
+    void cftrec4_th(int n, double *a, int nw, double *w);
+#endif /* USE_CDFT_THREADS */
+
+    if (n > 8)
+    {
+        if (n > 32)
+        {
+            cftb1st(n, a, &w[nw - (n >> 2)]);
+#ifdef USE_CDFT_THREADS
+            if (n > CDFT_THREADS_BEGIN_N)
+            {
+                cftrec4_th(n, a, nw, w);
+            }
+            else
+#endif /* USE_CDFT_THREADS */
+                if (n > 512)
+                {
+                    cftrec4(n, a, nw, w);
+                }
+                else if (n > 128)
+                {
+                    cftleaf(n, 1, a, nw, w);
+                }
+                else
+                {
+                    cftfx41(n, a, nw, w);
+                }
+            bitrv2conj(n, ip, a);
+        }
+        else if (n == 32)
+        {
+            cftf161(a, &w[nw - 8]);
+            bitrv216neg(a);
+        }
+        else
+        {
+            cftf081(a, w);
+            bitrv208neg(a);
+        }
+    }
+    else if (n == 8)
+    {
+        cftb040(a);
+    }
+    else if (n == 4)
+    {
+        cftx020(a);
+    }
+}
+
+
+void bitrv2(int n, int *ip, double *a)
+{
+    int j, j1, k, k1, l, m, nh, nm;
+    double xr, xi, yr, yi;
+
+    m = 1;
+    for (l = n >> 2; l > 8; l >>= 2)
+    {
+        m <<= 1;
+    }
+    nh = n >> 1;
+    nm = 4 * m;
+    if (l == 8)
+    {
+        for (k = 0; k < m; k++)
+        {
+            for (j = 0; j < k; j++)
+            {
+                j1 = 4 * j + 2 * ip[m + k];
+                k1 = 4 * k + 2 * ip[m + j];
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nh;
+                k1 += 2;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += 2;
+                k1 += nh;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nh;
+                k1 -= 2;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+            }
+            k1 = 4 * k + 2 * ip[m + k];
+            j1 = k1 + 2;
+            k1 += nh;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nm;
+            k1 += 2 * nm;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nm;
+            k1 -= nm;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 -= 2;
+            k1 -= nh;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nh + 2;
+            k1 += nh + 2;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 -= nh - nm;
+            k1 += 2 * nm - 2;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+        }
+    }
+    else
+    {
+        for (k = 0; k < m; k++)
+        {
+            for (j = 0; j < k; j++)
+            {
+                j1 = 4 * j + ip[m + k];
+                k1 = 4 * k + ip[m + j];
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nh;
+                k1 += 2;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += 2;
+                k1 += nh;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nh;
+                k1 -= 2;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = a[j1 + 1];
+                yr = a[k1];
+                yi = a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+            }
+            k1 = 4 * k + ip[m + k];
+            j1 = k1 + 2;
+            k1 += nh;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nm;
+            k1 += nm;
+            xr = a[j1];
+            xi = a[j1 + 1];
+            yr = a[k1];
+            yi = a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+        }
+    }
+}
+
+
+void bitrv2conj(int n, int *ip, double *a)
+{
+    int j, j1, k, k1, l, m, nh, nm;
+    double xr, xi, yr, yi;
+
+    m = 1;
+    for (l = n >> 2; l > 8; l >>= 2)
+    {
+        m <<= 1;
+    }
+    nh = n >> 1;
+    nm = 4 * m;
+    if (l == 8)
+    {
+        for (k = 0; k < m; k++)
+        {
+            for (j = 0; j < k; j++)
+            {
+                j1 = 4 * j + 2 * ip[m + k];
+                k1 = 4 * k + 2 * ip[m + j];
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nh;
+                k1 += 2;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += 2;
+                k1 += nh;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nh;
+                k1 -= 2;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= 2 * nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+            }
+            k1 = 4 * k + 2 * ip[m + k];
+            j1 = k1 + 2;
+            k1 += nh;
+            a[j1 - 1] = -a[j1 - 1];
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            a[k1 + 3] = -a[k1 + 3];
+            j1 += nm;
+            k1 += 2 * nm;
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nm;
+            k1 -= nm;
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 -= 2;
+            k1 -= nh;
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 += nh + 2;
+            k1 += nh + 2;
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            j1 -= nh - nm;
+            k1 += 2 * nm - 2;
+            a[j1 - 1] = -a[j1 - 1];
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            a[k1 + 3] = -a[k1 + 3];
+        }
+    }
+    else
+    {
+        for (k = 0; k < m; k++)
+        {
+            for (j = 0; j < k; j++)
+            {
+                j1 = 4 * j + ip[m + k];
+                k1 = 4 * k + ip[m + j];
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nh;
+                k1 += 2;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += 2;
+                k1 += nh;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 += nm;
+                k1 += nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nh;
+                k1 -= 2;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+                j1 -= nm;
+                k1 -= nm;
+                xr = a[j1];
+                xi = -a[j1 + 1];
+                yr = a[k1];
+                yi = -a[k1 + 1];
+                a[j1] = yr;
+                a[j1 + 1] = yi;
+                a[k1] = xr;
+                a[k1 + 1] = xi;
+            }
+            k1 = 4 * k + ip[m + k];
+            j1 = k1 + 2;
+            k1 += nh;
+            a[j1 - 1] = -a[j1 - 1];
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            a[k1 + 3] = -a[k1 + 3];
+            j1 += nm;
+            k1 += nm;
+            a[j1 - 1] = -a[j1 - 1];
+            xr = a[j1];
+            xi = -a[j1 + 1];
+            yr = a[k1];
+            yi = -a[k1 + 1];
+            a[j1] = yr;
+            a[j1 + 1] = yi;
+            a[k1] = xr;
+            a[k1 + 1] = xi;
+            a[k1 + 3] = -a[k1 + 3];
+        }
+    }
+}
+
+
+void bitrv216(double *a)
+{
+    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
+           x5r, x5i, x7r, x7i, x8r, x8i, x10r, x10i,
+           x11r, x11i, x12r, x12i, x13r, x13i, x14r, x14i;
+
+    x1r = a[2];
+    x1i = a[3];
+    x2r = a[4];
+    x2i = a[5];
+    x3r = a[6];
+    x3i = a[7];
+    x4r = a[8];
+    x4i = a[9];
+    x5r = a[10];
+    x5i = a[11];
+    x7r = a[14];
+    x7i = a[15];
+    x8r = a[16];
+    x8i = a[17];
+    x10r = a[20];
+    x10i = a[21];
+    x11r = a[22];
+    x11i = a[23];
+    x12r = a[24];
+    x12i = a[25];
+    x13r = a[26];
+    x13i = a[27];
+    x14r = a[28];
+    x14i = a[29];
+    a[2] = x8r;
+    a[3] = x8i;
+    a[4] = x4r;
+    a[5] = x4i;
+    a[6] = x12r;
+    a[7] = x12i;
+    a[8] = x2r;
+    a[9] = x2i;
+    a[10] = x10r;
+    a[11] = x10i;
+    a[14] = x14r;
+    a[15] = x14i;
+    a[16] = x1r;
+    a[17] = x1i;
+    a[20] = x5r;
+    a[21] = x5i;
+    a[22] = x13r;
+    a[23] = x13i;
+    a[24] = x3r;
+    a[25] = x3i;
+    a[26] = x11r;
+    a[27] = x11i;
+    a[28] = x7r;
+    a[29] = x7i;
+}
+
+
+void bitrv216neg(double *a)
+{
+    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
+           x5r, x5i, x6r, x6i, x7r, x7i, x8r, x8i,
+           x9r, x9i, x10r, x10i, x11r, x11i, x12r, x12i,
+           x13r, x13i, x14r, x14i, x15r, x15i;
+
+    x1r = a[2];
+    x1i = a[3];
+    x2r = a[4];
+    x2i = a[5];
+    x3r = a[6];
+    x3i = a[7];
+    x4r = a[8];
+    x4i = a[9];
+    x5r = a[10];
+    x5i = a[11];
+    x6r = a[12];
+    x6i = a[13];
+    x7r = a[14];
+    x7i = a[15];
+    x8r = a[16];
+    x8i = a[17];
+    x9r = a[18];
+    x9i = a[19];
+    x10r = a[20];
+    x10i = a[21];
+    x11r = a[22];
+    x11i = a[23];
+    x12r = a[24];
+    x12i = a[25];
+    x13r = a[26];
+    x13i = a[27];
+    x14r = a[28];
+    x14i = a[29];
+    x15r = a[30];
+    x15i = a[31];
+    a[2] = x15r;
+    a[3] = x15i;
+    a[4] = x7r;
+    a[5] = x7i;
+    a[6] = x11r;
+    a[7] = x11i;
+    a[8] = x3r;
+    a[9] = x3i;
+    a[10] = x13r;
+    a[11] = x13i;
+    a[12] = x5r;
+    a[13] = x5i;
+    a[14] = x9r;
+    a[15] = x9i;
+    a[16] = x1r;
+    a[17] = x1i;
+    a[18] = x14r;
+    a[19] = x14i;
+    a[20] = x6r;
+    a[21] = x6i;
+    a[22] = x10r;
+    a[23] = x10i;
+    a[24] = x2r;
+    a[25] = x2i;
+    a[26] = x12r;
+    a[27] = x12i;
+    a[28] = x4r;
+    a[29] = x4i;
+    a[30] = x8r;
+    a[31] = x8i;
+}
+
+
+void bitrv208(double *a)
+{
+    double x1r, x1i, x3r, x3i, x4r, x4i, x6r, x6i;
+
+    x1r = a[2];
+    x1i = a[3];
+    x3r = a[6];
+    x3i = a[7];
+    x4r = a[8];
+    x4i = a[9];
+    x6r = a[12];
+    x6i = a[13];
+    a[2] = x4r;
+    a[3] = x4i;
+    a[6] = x6r;
+    a[7] = x6i;
+    a[8] = x1r;
+    a[9] = x1i;
+    a[12] = x3r;
+    a[13] = x3i;
+}
+
+
+void bitrv208neg(double *a)
+{
+    double x1r, x1i, x2r, x2i, x3r, x3i, x4r, x4i,
+           x5r, x5i, x6r, x6i, x7r, x7i;
+
+    x1r = a[2];
+    x1i = a[3];
+    x2r = a[4];
+    x2i = a[5];
+    x3r = a[6];
+    x3i = a[7];
+    x4r = a[8];
+    x4i = a[9];
+    x5r = a[10];
+    x5i = a[11];
+    x6r = a[12];
+    x6i = a[13];
+    x7r = a[14];
+    x7i = a[15];
+    a[2] = x7r;
+    a[3] = x7i;
+    a[4] = x3r;
+    a[5] = x3i;
+    a[6] = x5r;
+    a[7] = x5i;
+    a[8] = x1r;
+    a[9] = x1i;
+    a[10] = x6r;
+    a[11] = x6i;
+    a[12] = x2r;
+    a[13] = x2i;
+    a[14] = x4r;
+    a[15] = x4i;
+}
+
+
+void cftf1st(int n, double *a, double *w)
+{
+    int j, j0, j1, j2, j3, k, m, mh;
+    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i,
+           wd1r, wd1i, wd3r, wd3i;
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i;
+
+    mh = n >> 3;
+    m = 2 * mh;
+    j1 = m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[0] + a[j2];
+    x0i = a[1] + a[j2 + 1];
+    x1r = a[0] - a[j2];
+    x1i = a[1] - a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[0] = x0r + x2r;
+    a[1] = x0i + x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i - x2i;
+    a[j2] = x1r - x3i;
+    a[j2 + 1] = x1i + x3r;
+    a[j3] = x1r + x3i;
+    a[j3 + 1] = x1i - x3r;
+    wn4r = w[1];
+    csc1 = w[2];
+    csc3 = w[3];
+    wd1r = 1;
+    wd1i = 0;
+    wd3r = 1;
+    wd3i = 0;
+    k = 0;
+    for (j = 2; j < mh - 2; j += 4)
+    {
+        k += 4;
+        wk1r = csc1 * (wd1r + w[k]);
+        wk1i = csc1 * (wd1i + w[k + 1]);
+        wk3r = csc3 * (wd3r + w[k + 2]);
+        wk3i = csc3 * (wd3i + w[k + 3]);
+        wd1r = w[k];
+        wd1i = w[k + 1];
+        wd3r = w[k + 2];
+        wd3i = w[k + 3];
+        j1 = j + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j] + a[j2];
+        x0i = a[j + 1] + a[j2 + 1];
+        x1r = a[j] - a[j2];
+        x1i = a[j + 1] - a[j2 + 1];
+        y0r = a[j + 2] + a[j2 + 2];
+        y0i = a[j + 3] + a[j2 + 3];
+        y1r = a[j + 2] - a[j2 + 2];
+        y1i = a[j + 3] - a[j2 + 3];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        y2r = a[j1 + 2] + a[j3 + 2];
+        y2i = a[j1 + 3] + a[j3 + 3];
+        y3r = a[j1 + 2] - a[j3 + 2];
+        y3i = a[j1 + 3] - a[j3 + 3];
+        a[j] = x0r + x2r;
+        a[j + 1] = x0i + x2i;
+        a[j + 2] = y0r + y2r;
+        a[j + 3] = y0i + y2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i - x2i;
+        a[j1 + 2] = y0r - y2r;
+        a[j1 + 3] = y0i - y2i;
+        x0r = x1r - x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1r * x0r - wk1i * x0i;
+        a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+        x0r = y1r - y3i;
+        x0i = y1i + y3r;
+        a[j2 + 2] = wd1r * x0r - wd1i * x0i;
+        a[j2 + 3] = wd1r * x0i + wd1i * x0r;
+        x0r = x1r + x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3r * x0r + wk3i * x0i;
+        a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+        x0r = y1r + y3i;
+        x0i = y1i - y3r;
+        a[j3 + 2] = wd3r * x0r + wd3i * x0i;
+        a[j3 + 3] = wd3r * x0i - wd3i * x0r;
+        j0 = m - j;
+        j1 = j0 + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j0] + a[j2];
+        x0i = a[j0 + 1] + a[j2 + 1];
+        x1r = a[j0] - a[j2];
+        x1i = a[j0 + 1] - a[j2 + 1];
+        y0r = a[j0 - 2] + a[j2 - 2];
+        y0i = a[j0 - 1] + a[j2 - 1];
+        y1r = a[j0 - 2] - a[j2 - 2];
+        y1i = a[j0 - 1] - a[j2 - 1];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        y2r = a[j1 - 2] + a[j3 - 2];
+        y2i = a[j1 - 1] + a[j3 - 1];
+        y3r = a[j1 - 2] - a[j3 - 2];
+        y3i = a[j1 - 1] - a[j3 - 1];
+        a[j0] = x0r + x2r;
+        a[j0 + 1] = x0i + x2i;
+        a[j0 - 2] = y0r + y2r;
+        a[j0 - 1] = y0i + y2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i - x2i;
+        a[j1 - 2] = y0r - y2r;
+        a[j1 - 1] = y0i - y2i;
+        x0r = x1r - x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1i * x0r - wk1r * x0i;
+        a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+        x0r = y1r - y3i;
+        x0i = y1i + y3r;
+        a[j2 - 2] = wd1i * x0r - wd1r * x0i;
+        a[j2 - 1] = wd1i * x0i + wd1r * x0r;
+        x0r = x1r + x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3i * x0r + wk3r * x0i;
+        a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+        x0r = y1r + y3i;
+        x0i = y1i - y3r;
+        a[j3 - 2] = wd3i * x0r + wd3r * x0i;
+        a[j3 - 1] = wd3i * x0i - wd3r * x0r;
+    }
+    wk1r = csc1 * (wd1r + wn4r);
+    wk1i = csc1 * (wd1i + wn4r);
+    wk3r = csc3 * (wd3r - wn4r);
+    wk3i = csc3 * (wd3i - wn4r);
+    j0 = mh;
+    j1 = j0 + m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[j0 - 2] + a[j2 - 2];
+    x0i = a[j0 - 1] + a[j2 - 1];
+    x1r = a[j0 - 2] - a[j2 - 2];
+    x1i = a[j0 - 1] - a[j2 - 1];
+    x2r = a[j1 - 2] + a[j3 - 2];
+    x2i = a[j1 - 1] + a[j3 - 1];
+    x3r = a[j1 - 2] - a[j3 - 2];
+    x3i = a[j1 - 1] - a[j3 - 1];
+    a[j0 - 2] = x0r + x2r;
+    a[j0 - 1] = x0i + x2i;
+    a[j1 - 2] = x0r - x2r;
+    a[j1 - 1] = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    a[j2 - 2] = wk1r * x0r - wk1i * x0i;
+    a[j2 - 1] = wk1r * x0i + wk1i * x0r;
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    a[j3 - 2] = wk3r * x0r + wk3i * x0i;
+    a[j3 - 1] = wk3r * x0i - wk3i * x0r;
+    x0r = a[j0] + a[j2];
+    x0i = a[j0 + 1] + a[j2 + 1];
+    x1r = a[j0] - a[j2];
+    x1i = a[j0 + 1] - a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[j0] = x0r + x2r;
+    a[j0 + 1] = x0i + x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    a[j2] = wn4r * (x0r - x0i);
+    a[j2 + 1] = wn4r * (x0i + x0r);
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    a[j3] = -wn4r * (x0r + x0i);
+    a[j3 + 1] = -wn4r * (x0i - x0r);
+    x0r = a[j0 + 2] + a[j2 + 2];
+    x0i = a[j0 + 3] + a[j2 + 3];
+    x1r = a[j0 + 2] - a[j2 + 2];
+    x1i = a[j0 + 3] - a[j2 + 3];
+    x2r = a[j1 + 2] + a[j3 + 2];
+    x2i = a[j1 + 3] + a[j3 + 3];
+    x3r = a[j1 + 2] - a[j3 + 2];
+    x3i = a[j1 + 3] - a[j3 + 3];
+    a[j0 + 2] = x0r + x2r;
+    a[j0 + 3] = x0i + x2i;
+    a[j1 + 2] = x0r - x2r;
+    a[j1 + 3] = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    a[j2 + 2] = wk1i * x0r - wk1r * x0i;
+    a[j2 + 3] = wk1i * x0i + wk1r * x0r;
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    a[j3 + 2] = wk3i * x0r + wk3r * x0i;
+    a[j3 + 3] = wk3i * x0i - wk3r * x0r;
+}
+
+
+void cftb1st(int n, double *a, double *w)
+{
+    int j, j0, j1, j2, j3, k, m, mh;
+    double wn4r, csc1, csc3, wk1r, wk1i, wk3r, wk3i,
+           wd1r, wd1i, wd3r, wd3i;
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i;
+
+    mh = n >> 3;
+    m = 2 * mh;
+    j1 = m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[0] + a[j2];
+    x0i = -a[1] - a[j2 + 1];
+    x1r = a[0] - a[j2];
+    x1i = -a[1] + a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[0] = x0r + x2r;
+    a[1] = x0i - x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i + x2i;
+    a[j2] = x1r + x3i;
+    a[j2 + 1] = x1i + x3r;
+    a[j3] = x1r - x3i;
+    a[j3 + 1] = x1i - x3r;
+    wn4r = w[1];
+    csc1 = w[2];
+    csc3 = w[3];
+    wd1r = 1;
+    wd1i = 0;
+    wd3r = 1;
+    wd3i = 0;
+    k = 0;
+    for (j = 2; j < mh - 2; j += 4)
+    {
+        k += 4;
+        wk1r = csc1 * (wd1r + w[k]);
+        wk1i = csc1 * (wd1i + w[k + 1]);
+        wk3r = csc3 * (wd3r + w[k + 2]);
+        wk3i = csc3 * (wd3i + w[k + 3]);
+        wd1r = w[k];
+        wd1i = w[k + 1];
+        wd3r = w[k + 2];
+        wd3i = w[k + 3];
+        j1 = j + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j] + a[j2];
+        x0i = -a[j + 1] - a[j2 + 1];
+        x1r = a[j] - a[j2];
+        x1i = -a[j + 1] + a[j2 + 1];
+        y0r = a[j + 2] + a[j2 + 2];
+        y0i = -a[j + 3] - a[j2 + 3];
+        y1r = a[j + 2] - a[j2 + 2];
+        y1i = -a[j + 3] + a[j2 + 3];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        y2r = a[j1 + 2] + a[j3 + 2];
+        y2i = a[j1 + 3] + a[j3 + 3];
+        y3r = a[j1 + 2] - a[j3 + 2];
+        y3i = a[j1 + 3] - a[j3 + 3];
+        a[j] = x0r + x2r;
+        a[j + 1] = x0i - x2i;
+        a[j + 2] = y0r + y2r;
+        a[j + 3] = y0i - y2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i + x2i;
+        a[j1 + 2] = y0r - y2r;
+        a[j1 + 3] = y0i + y2i;
+        x0r = x1r + x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1r * x0r - wk1i * x0i;
+        a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+        x0r = y1r + y3i;
+        x0i = y1i + y3r;
+        a[j2 + 2] = wd1r * x0r - wd1i * x0i;
+        a[j2 + 3] = wd1r * x0i + wd1i * x0r;
+        x0r = x1r - x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3r * x0r + wk3i * x0i;
+        a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+        x0r = y1r - y3i;
+        x0i = y1i - y3r;
+        a[j3 + 2] = wd3r * x0r + wd3i * x0i;
+        a[j3 + 3] = wd3r * x0i - wd3i * x0r;
+        j0 = m - j;
+        j1 = j0 + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j0] + a[j2];
+        x0i = -a[j0 + 1] - a[j2 + 1];
+        x1r = a[j0] - a[j2];
+        x1i = -a[j0 + 1] + a[j2 + 1];
+        y0r = a[j0 - 2] + a[j2 - 2];
+        y0i = -a[j0 - 1] - a[j2 - 1];
+        y1r = a[j0 - 2] - a[j2 - 2];
+        y1i = -a[j0 - 1] + a[j2 - 1];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        y2r = a[j1 - 2] + a[j3 - 2];
+        y2i = a[j1 - 1] + a[j3 - 1];
+        y3r = a[j1 - 2] - a[j3 - 2];
+        y3i = a[j1 - 1] - a[j3 - 1];
+        a[j0] = x0r + x2r;
+        a[j0 + 1] = x0i - x2i;
+        a[j0 - 2] = y0r + y2r;
+        a[j0 - 1] = y0i - y2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i + x2i;
+        a[j1 - 2] = y0r - y2r;
+        a[j1 - 1] = y0i + y2i;
+        x0r = x1r + x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1i * x0r - wk1r * x0i;
+        a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+        x0r = y1r + y3i;
+        x0i = y1i + y3r;
+        a[j2 - 2] = wd1i * x0r - wd1r * x0i;
+        a[j2 - 1] = wd1i * x0i + wd1r * x0r;
+        x0r = x1r - x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3i * x0r + wk3r * x0i;
+        a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+        x0r = y1r - y3i;
+        x0i = y1i - y3r;
+        a[j3 - 2] = wd3i * x0r + wd3r * x0i;
+        a[j3 - 1] = wd3i * x0i - wd3r * x0r;
+    }
+    wk1r = csc1 * (wd1r + wn4r);
+    wk1i = csc1 * (wd1i + wn4r);
+    wk3r = csc3 * (wd3r - wn4r);
+    wk3i = csc3 * (wd3i - wn4r);
+    j0 = mh;
+    j1 = j0 + m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[j0 - 2] + a[j2 - 2];
+    x0i = -a[j0 - 1] - a[j2 - 1];
+    x1r = a[j0 - 2] - a[j2 - 2];
+    x1i = -a[j0 - 1] + a[j2 - 1];
+    x2r = a[j1 - 2] + a[j3 - 2];
+    x2i = a[j1 - 1] + a[j3 - 1];
+    x3r = a[j1 - 2] - a[j3 - 2];
+    x3i = a[j1 - 1] - a[j3 - 1];
+    a[j0 - 2] = x0r + x2r;
+    a[j0 - 1] = x0i - x2i;
+    a[j1 - 2] = x0r - x2r;
+    a[j1 - 1] = x0i + x2i;
+    x0r = x1r + x3i;
+    x0i = x1i + x3r;
+    a[j2 - 2] = wk1r * x0r - wk1i * x0i;
+    a[j2 - 1] = wk1r * x0i + wk1i * x0r;
+    x0r = x1r - x3i;
+    x0i = x1i - x3r;
+    a[j3 - 2] = wk3r * x0r + wk3i * x0i;
+    a[j3 - 1] = wk3r * x0i - wk3i * x0r;
+    x0r = a[j0] + a[j2];
+    x0i = -a[j0 + 1] - a[j2 + 1];
+    x1r = a[j0] - a[j2];
+    x1i = -a[j0 + 1] + a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[j0] = x0r + x2r;
+    a[j0 + 1] = x0i - x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i + x2i;
+    x0r = x1r + x3i;
+    x0i = x1i + x3r;
+    a[j2] = wn4r * (x0r - x0i);
+    a[j2 + 1] = wn4r * (x0i + x0r);
+    x0r = x1r - x3i;
+    x0i = x1i - x3r;
+    a[j3] = -wn4r * (x0r + x0i);
+    a[j3 + 1] = -wn4r * (x0i - x0r);
+    x0r = a[j0 + 2] + a[j2 + 2];
+    x0i = -a[j0 + 3] - a[j2 + 3];
+    x1r = a[j0 + 2] - a[j2 + 2];
+    x1i = -a[j0 + 3] + a[j2 + 3];
+    x2r = a[j1 + 2] + a[j3 + 2];
+    x2i = a[j1 + 3] + a[j3 + 3];
+    x3r = a[j1 + 2] - a[j3 + 2];
+    x3i = a[j1 + 3] - a[j3 + 3];
+    a[j0 + 2] = x0r + x2r;
+    a[j0 + 3] = x0i - x2i;
+    a[j1 + 2] = x0r - x2r;
+    a[j1 + 3] = x0i + x2i;
+    x0r = x1r + x3i;
+    x0i = x1i + x3r;
+    a[j2 + 2] = wk1i * x0r - wk1r * x0i;
+    a[j2 + 3] = wk1i * x0i + wk1r * x0r;
+    x0r = x1r - x3i;
+    x0i = x1i - x3r;
+    a[j3 + 2] = wk3i * x0r + wk3r * x0i;
+    a[j3 + 3] = wk3i * x0i - wk3r * x0r;
+}
+
+
+#ifdef USE_CDFT_THREADS
+struct cdft_arg_st
+{
+    int n0;
+    int n;
+    double *a;
+    int nw;
+    double *w;
+};
+typedef struct cdft_arg_st cdft_arg_t;
+
+
+void cftrec4_th(int n, double *a, int nw, double *w)
+{
+    void *cftrec1_th(void *p);
+    void *cftrec2_th(void *p);
+    int i, idiv4, m, nthread;
+    cdft_thread_t th[4];
+    cdft_arg_t ag[4];
+
+    nthread = 2;
+    idiv4 = 0;
+    m = n >> 1;
+    if (n > CDFT_4THREADS_BEGIN_N)
+    {
+        nthread = 4;
+        idiv4 = 1;
+        m >>= 1;
+    }
+    for (i = 0; i < nthread; i++)
+    {
+        ag[i].n0 = n;
+        ag[i].n = m;
+        ag[i].a = &a[i * m];
+        ag[i].nw = nw;
+        ag[i].w = w;
+        if (i != idiv4)
+        {
+            cdft_thread_create(&th[i], cftrec1_th, &ag[i]);
+        }
+        else
+        {
+            cdft_thread_create(&th[i], cftrec2_th, &ag[i]);
+        }
+    }
+    for (i = 0; i < nthread; i++)
+    {
+        cdft_thread_wait(th[i]);
+    }
+}
+
+
+void *cftrec1_th(void *p)
+{
+    int cfttree(int n, int j, int k, double *a, int nw, double *w);
+    void cftleaf(int n, int isplt, double *a, int nw, double *w);
+    void cftmdl1(int n, double *a, double *w);
+    int isplt, j, k, m, n, n0, nw;
+    double *a, *w;
+
+    n0 = ((cdft_arg_t *) p)->n0;
+    n = ((cdft_arg_t *) p)->n;
+    a = ((cdft_arg_t *) p)->a;
+    nw = ((cdft_arg_t *) p)->nw;
+    w = ((cdft_arg_t *) p)->w;
+    m = n0;
+    while (m > 512)
+    {
+        m >>= 2;
+        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);
+    }
+    cftleaf(m, 1, &a[n - m], nw, w);
+    k = 0;
+    for (j = n - m; j > 0; j -= m)
+    {
+        k++;
+        isplt = cfttree(m, j, k, a, nw, w);
+        cftleaf(m, isplt, &a[j - m], nw, w);
+    }
+    return (void *) 0;
+}
+
+
+void *cftrec2_th(void *p)
+{
+    int cfttree(int n, int j, int k, double *a, int nw, double *w);
+    void cftleaf(int n, int isplt, double *a, int nw, double *w);
+    void cftmdl2(int n, double *a, double *w);
+    int isplt, j, k, m, n, n0, nw;
+    double *a, *w;
+
+    n0 = ((cdft_arg_t *) p)->n0;
+    n = ((cdft_arg_t *) p)->n;
+    a = ((cdft_arg_t *) p)->a;
+    nw = ((cdft_arg_t *) p)->nw;
+    w = ((cdft_arg_t *) p)->w;
+    k = 1;
+    m = n0;
+    while (m > 512)
+    {
+        m >>= 2;
+        k <<= 2;
+        cftmdl2(m, &a[n - m], &w[nw - m]);
+    }
+    cftleaf(m, 0, &a[n - m], nw, w);
+    k >>= 1;
+    for (j = n - m; j > 0; j -= m)
+    {
+        k++;
+        isplt = cfttree(m, j, k, a, nw, w);
+        cftleaf(m, isplt, &a[j - m], nw, w);
+    }
+    return (void *) 0;
+}
+#endif /* USE_CDFT_THREADS */
+
+
+void cftrec4(int n, double *a, int nw, double *w)
+{
+    int cfttree(int n, int j, int k, double *a, int nw, double *w);
+    void cftleaf(int n, int isplt, double *a, int nw, double *w);
+    void cftmdl1(int n, double *a, double *w);
+    int isplt, j, k, m;
+
+    m = n;
+    while (m > 512)
+    {
+        m >>= 2;
+        cftmdl1(m, &a[n - m], &w[nw - (m >> 1)]);
+    }
+    cftleaf(m, 1, &a[n - m], nw, w);
+    k = 0;
+    for (j = n - m; j > 0; j -= m)
+    {
+        k++;
+        isplt = cfttree(m, j, k, a, nw, w);
+        cftleaf(m, isplt, &a[j - m], nw, w);
+    }
+}
+
+
+int cfttree(int n, int j, int k, double *a, int nw, double *w)
+{
+    void cftmdl1(int n, double *a, double *w);
+    void cftmdl2(int n, double *a, double *w);
+    int i, isplt, m;
+
+    if ((k & 3) != 0)
+    {
+        isplt = k & 1;
+        if (isplt != 0)
+        {
+            cftmdl1(n, &a[j - n], &w[nw - (n >> 1)]);
+        }
+        else
+        {
+            cftmdl2(n, &a[j - n], &w[nw - n]);
+        }
+    }
+    else
+    {
+        m = n;
+        for (i = k; (i & 3) == 0; i >>= 2)
+        {
+            m <<= 2;
+        }
+        isplt = i & 1;
+        if (isplt != 0)
+        {
+            while (m > 128)
+            {
+                cftmdl1(m, &a[j - m], &w[nw - (m >> 1)]);
+                m >>= 2;
+            }
+        }
+        else
+        {
+            while (m > 128)
+            {
+                cftmdl2(m, &a[j - m], &w[nw - m]);
+                m >>= 2;
+            }
+        }
+    }
+    return isplt;
+}
+
+
+void cftleaf(int n, int isplt, double *a, int nw, double *w)
+{
+    void cftmdl1(int n, double *a, double *w);
+    void cftmdl2(int n, double *a, double *w);
+    void cftf161(double *a, double *w);
+    void cftf162(double *a, double *w);
+    void cftf081(double *a, double *w);
+    void cftf082(double *a, double *w);
+
+    if (n == 512)
+    {
+        cftmdl1(128, a, &w[nw - 64]);
+        cftf161(a, &w[nw - 8]);
+        cftf162(&a[32], &w[nw - 32]);
+        cftf161(&a[64], &w[nw - 8]);
+        cftf161(&a[96], &w[nw - 8]);
+        cftmdl2(128, &a[128], &w[nw - 128]);
+        cftf161(&a[128], &w[nw - 8]);
+        cftf162(&a[160], &w[nw - 32]);
+        cftf161(&a[192], &w[nw - 8]);
+        cftf162(&a[224], &w[nw - 32]);
+        cftmdl1(128, &a[256], &w[nw - 64]);
+        cftf161(&a[256], &w[nw - 8]);
+        cftf162(&a[288], &w[nw - 32]);
+        cftf161(&a[320], &w[nw - 8]);
+        cftf161(&a[352], &w[nw - 8]);
+        if (isplt != 0)
+        {
+            cftmdl1(128, &a[384], &w[nw - 64]);
+            cftf161(&a[480], &w[nw - 8]);
+        }
+        else
+        {
+            cftmdl2(128, &a[384], &w[nw - 128]);
+            cftf162(&a[480], &w[nw - 32]);
+        }
+        cftf161(&a[384], &w[nw - 8]);
+        cftf162(&a[416], &w[nw - 32]);
+        cftf161(&a[448], &w[nw - 8]);
+    }
+    else
+    {
+        cftmdl1(64, a, &w[nw - 32]);
+        cftf081(a, &w[nw - 8]);
+        cftf082(&a[16], &w[nw - 8]);
+        cftf081(&a[32], &w[nw - 8]);
+        cftf081(&a[48], &w[nw - 8]);
+        cftmdl2(64, &a[64], &w[nw - 64]);
+        cftf081(&a[64], &w[nw - 8]);
+        cftf082(&a[80], &w[nw - 8]);
+        cftf081(&a[96], &w[nw - 8]);
+        cftf082(&a[112], &w[nw - 8]);
+        cftmdl1(64, &a[128], &w[nw - 32]);
+        cftf081(&a[128], &w[nw - 8]);
+        cftf082(&a[144], &w[nw - 8]);
+        cftf081(&a[160], &w[nw - 8]);
+        cftf081(&a[176], &w[nw - 8]);
+        if (isplt != 0)
+        {
+            cftmdl1(64, &a[192], &w[nw - 32]);
+            cftf081(&a[240], &w[nw - 8]);
+        }
+        else
+        {
+            cftmdl2(64, &a[192], &w[nw - 64]);
+            cftf082(&a[240], &w[nw - 8]);
+        }
+        cftf081(&a[192], &w[nw - 8]);
+        cftf082(&a[208], &w[nw - 8]);
+        cftf081(&a[224], &w[nw - 8]);
+    }
+}
+
+
+void cftmdl1(int n, double *a, double *w)
+{
+    int j, j0, j1, j2, j3, k, m, mh;
+    double wn4r, wk1r, wk1i, wk3r, wk3i;
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+    mh = n >> 3;
+    m = 2 * mh;
+    j1 = m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[0] + a[j2];
+    x0i = a[1] + a[j2 + 1];
+    x1r = a[0] - a[j2];
+    x1i = a[1] - a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[0] = x0r + x2r;
+    a[1] = x0i + x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i - x2i;
+    a[j2] = x1r - x3i;
+    a[j2 + 1] = x1i + x3r;
+    a[j3] = x1r + x3i;
+    a[j3 + 1] = x1i - x3r;
+    wn4r = w[1];
+    k = 0;
+    for (j = 2; j < mh; j += 2)
+    {
+        k += 4;
+        wk1r = w[k];
+        wk1i = w[k + 1];
+        wk3r = w[k + 2];
+        wk3i = w[k + 3];
+        j1 = j + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j] + a[j2];
+        x0i = a[j + 1] + a[j2 + 1];
+        x1r = a[j] - a[j2];
+        x1i = a[j + 1] - a[j2 + 1];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        a[j] = x0r + x2r;
+        a[j + 1] = x0i + x2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i - x2i;
+        x0r = x1r - x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1r * x0r - wk1i * x0i;
+        a[j2 + 1] = wk1r * x0i + wk1i * x0r;
+        x0r = x1r + x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3r * x0r + wk3i * x0i;
+        a[j3 + 1] = wk3r * x0i - wk3i * x0r;
+        j0 = m - j;
+        j1 = j0 + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j0] + a[j2];
+        x0i = a[j0 + 1] + a[j2 + 1];
+        x1r = a[j0] - a[j2];
+        x1i = a[j0 + 1] - a[j2 + 1];
+        x2r = a[j1] + a[j3];
+        x2i = a[j1 + 1] + a[j3 + 1];
+        x3r = a[j1] - a[j3];
+        x3i = a[j1 + 1] - a[j3 + 1];
+        a[j0] = x0r + x2r;
+        a[j0 + 1] = x0i + x2i;
+        a[j1] = x0r - x2r;
+        a[j1 + 1] = x0i - x2i;
+        x0r = x1r - x3i;
+        x0i = x1i + x3r;
+        a[j2] = wk1i * x0r - wk1r * x0i;
+        a[j2 + 1] = wk1i * x0i + wk1r * x0r;
+        x0r = x1r + x3i;
+        x0i = x1i - x3r;
+        a[j3] = wk3i * x0r + wk3r * x0i;
+        a[j3 + 1] = wk3i * x0i - wk3r * x0r;
+    }
+    j0 = mh;
+    j1 = j0 + m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[j0] + a[j2];
+    x0i = a[j0 + 1] + a[j2 + 1];
+    x1r = a[j0] - a[j2];
+    x1i = a[j0 + 1] - a[j2 + 1];
+    x2r = a[j1] + a[j3];
+    x2i = a[j1 + 1] + a[j3 + 1];
+    x3r = a[j1] - a[j3];
+    x3i = a[j1 + 1] - a[j3 + 1];
+    a[j0] = x0r + x2r;
+    a[j0 + 1] = x0i + x2i;
+    a[j1] = x0r - x2r;
+    a[j1 + 1] = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    a[j2] = wn4r * (x0r - x0i);
+    a[j2 + 1] = wn4r * (x0i + x0r);
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    a[j3] = -wn4r * (x0r + x0i);
+    a[j3 + 1] = -wn4r * (x0i - x0r);
+}
+
+
+void cftmdl2(int n, double *a, double *w)
+{
+    int j, j0, j1, j2, j3, k, kr, m, mh;
+    double wn4r, wk1r, wk1i, wk3r, wk3i, wd1r, wd1i, wd3r, wd3i;
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i, y0r, y0i, y2r, y2i;
+
+    mh = n >> 3;
+    m = 2 * mh;
+    wn4r = w[1];
+    j1 = m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[0] - a[j2 + 1];
+    x0i = a[1] + a[j2];
+    x1r = a[0] + a[j2 + 1];
+    x1i = a[1] - a[j2];
+    x2r = a[j1] - a[j3 + 1];
+    x2i = a[j1 + 1] + a[j3];
+    x3r = a[j1] + a[j3 + 1];
+    x3i = a[j1 + 1] - a[j3];
+    y0r = wn4r * (x2r - x2i);
+    y0i = wn4r * (x2i + x2r);
+    a[0] = x0r + y0r;
+    a[1] = x0i + y0i;
+    a[j1] = x0r - y0r;
+    a[j1 + 1] = x0i - y0i;
+    y0r = wn4r * (x3r - x3i);
+    y0i = wn4r * (x3i + x3r);
+    a[j2] = x1r - y0i;
+    a[j2 + 1] = x1i + y0r;
+    a[j3] = x1r + y0i;
+    a[j3 + 1] = x1i - y0r;
+    k = 0;
+    kr = 2 * m;
+    for (j = 2; j < mh; j += 2)
+    {
+        k += 4;
+        wk1r = w[k];
+        wk1i = w[k + 1];
+        wk3r = w[k + 2];
+        wk3i = w[k + 3];
+        kr -= 4;
+        wd1i = w[kr];
+        wd1r = w[kr + 1];
+        wd3i = w[kr + 2];
+        wd3r = w[kr + 3];
+        j1 = j + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j] - a[j2 + 1];
+        x0i = a[j + 1] + a[j2];
+        x1r = a[j] + a[j2 + 1];
+        x1i = a[j + 1] - a[j2];
+        x2r = a[j1] - a[j3 + 1];
+        x2i = a[j1 + 1] + a[j3];
+        x3r = a[j1] + a[j3 + 1];
+        x3i = a[j1 + 1] - a[j3];
+        y0r = wk1r * x0r - wk1i * x0i;
+        y0i = wk1r * x0i + wk1i * x0r;
+        y2r = wd1r * x2r - wd1i * x2i;
+        y2i = wd1r * x2i + wd1i * x2r;
+        a[j] = y0r + y2r;
+        a[j + 1] = y0i + y2i;
+        a[j1] = y0r - y2r;
+        a[j1 + 1] = y0i - y2i;
+        y0r = wk3r * x1r + wk3i * x1i;
+        y0i = wk3r * x1i - wk3i * x1r;
+        y2r = wd3r * x3r + wd3i * x3i;
+        y2i = wd3r * x3i - wd3i * x3r;
+        a[j2] = y0r + y2r;
+        a[j2 + 1] = y0i + y2i;
+        a[j3] = y0r - y2r;
+        a[j3 + 1] = y0i - y2i;
+        j0 = m - j;
+        j1 = j0 + m;
+        j2 = j1 + m;
+        j3 = j2 + m;
+        x0r = a[j0] - a[j2 + 1];
+        x0i = a[j0 + 1] + a[j2];
+        x1r = a[j0] + a[j2 + 1];
+        x1i = a[j0 + 1] - a[j2];
+        x2r = a[j1] - a[j3 + 1];
+        x2i = a[j1 + 1] + a[j3];
+        x3r = a[j1] + a[j3 + 1];
+        x3i = a[j1 + 1] - a[j3];
+        y0r = wd1i * x0r - wd1r * x0i;
+        y0i = wd1i * x0i + wd1r * x0r;
+        y2r = wk1i * x2r - wk1r * x2i;
+        y2i = wk1i * x2i + wk1r * x2r;
+        a[j0] = y0r + y2r;
+        a[j0 + 1] = y0i + y2i;
+        a[j1] = y0r - y2r;
+        a[j1 + 1] = y0i - y2i;
+        y0r = wd3i * x1r + wd3r * x1i;
+        y0i = wd3i * x1i - wd3r * x1r;
+        y2r = wk3i * x3r + wk3r * x3i;
+        y2i = wk3i * x3i - wk3r * x3r;
+        a[j2] = y0r + y2r;
+        a[j2 + 1] = y0i + y2i;
+        a[j3] = y0r - y2r;
+        a[j3 + 1] = y0i - y2i;
+    }
+    wk1r = w[m];
+    wk1i = w[m + 1];
+    j0 = mh;
+    j1 = j0 + m;
+    j2 = j1 + m;
+    j3 = j2 + m;
+    x0r = a[j0] - a[j2 + 1];
+    x0i = a[j0 + 1] + a[j2];
+    x1r = a[j0] + a[j2 + 1];
+    x1i = a[j0 + 1] - a[j2];
+    x2r = a[j1] - a[j3 + 1];
+    x2i = a[j1 + 1] + a[j3];
+    x3r = a[j1] + a[j3 + 1];
+    x3i = a[j1 + 1] - a[j3];
+    y0r = wk1r * x0r - wk1i * x0i;
+    y0i = wk1r * x0i + wk1i * x0r;
+    y2r = wk1i * x2r - wk1r * x2i;
+    y2i = wk1i * x2i + wk1r * x2r;
+    a[j0] = y0r + y2r;
+    a[j0 + 1] = y0i + y2i;
+    a[j1] = y0r - y2r;
+    a[j1 + 1] = y0i - y2i;
+    y0r = wk1i * x1r - wk1r * x1i;
+    y0i = wk1i * x1i + wk1r * x1r;
+    y2r = wk1r * x3r - wk1i * x3i;
+    y2i = wk1r * x3i + wk1i * x3r;
+    a[j2] = y0r - y2r;
+    a[j2 + 1] = y0i - y2i;
+    a[j3] = y0r + y2r;
+    a[j3 + 1] = y0i + y2i;
+}
+
+
+void cftfx41(int n, double *a, int nw, double *w)
+{
+    void cftf161(double *a, double *w);
+    void cftf162(double *a, double *w);
+    void cftf081(double *a, double *w);
+    void cftf082(double *a, double *w);
+
+    if (n == 128)
+    {
+        cftf161(a, &w[nw - 8]);
+        cftf162(&a[32], &w[nw - 32]);
+        cftf161(&a[64], &w[nw - 8]);
+        cftf161(&a[96], &w[nw - 8]);
+    }
+    else
+    {
+        cftf081(a, &w[nw - 8]);
+        cftf082(&a[16], &w[nw - 8]);
+        cftf081(&a[32], &w[nw - 8]);
+        cftf081(&a[48], &w[nw - 8]);
+    }
+}
+
+
+void cftf161(double *a, double *w)
+{
+    double wn4r, wk1r, wk1i,
+           x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
+           y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,
+           y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i,
+           y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i;
+
+    wn4r = w[1];
+    wk1r = w[2];
+    wk1i = w[3];
+    x0r = a[0] + a[16];
+    x0i = a[1] + a[17];
+    x1r = a[0] - a[16];
+    x1i = a[1] - a[17];
+    x2r = a[8] + a[24];
+    x2i = a[9] + a[25];
+    x3r = a[8] - a[24];
+    x3i = a[9] - a[25];
+    y0r = x0r + x2r;
+    y0i = x0i + x2i;
+    y4r = x0r - x2r;
+    y4i = x0i - x2i;
+    y8r = x1r - x3i;
+    y8i = x1i + x3r;
+    y12r = x1r + x3i;
+    y12i = x1i - x3r;
+    x0r = a[2] + a[18];
+    x0i = a[3] + a[19];
+    x1r = a[2] - a[18];
+    x1i = a[3] - a[19];
+    x2r = a[10] + a[26];
+    x2i = a[11] + a[27];
+    x3r = a[10] - a[26];
+    x3i = a[11] - a[27];
+    y1r = x0r + x2r;
+    y1i = x0i + x2i;
+    y5r = x0r - x2r;
+    y5i = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    y9r = wk1r * x0r - wk1i * x0i;
+    y9i = wk1r * x0i + wk1i * x0r;
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    y13r = wk1i * x0r - wk1r * x0i;
+    y13i = wk1i * x0i + wk1r * x0r;
+    x0r = a[4] + a[20];
+    x0i = a[5] + a[21];
+    x1r = a[4] - a[20];
+    x1i = a[5] - a[21];
+    x2r = a[12] + a[28];
+    x2i = a[13] + a[29];
+    x3r = a[12] - a[28];
+    x3i = a[13] - a[29];
+    y2r = x0r + x2r;
+    y2i = x0i + x2i;
+    y6r = x0r - x2r;
+    y6i = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    y10r = wn4r * (x0r - x0i);
+    y10i = wn4r * (x0i + x0r);
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    y14r = wn4r * (x0r + x0i);
+    y14i = wn4r * (x0i - x0r);
+    x0r = a[6] + a[22];
+    x0i = a[7] + a[23];
+    x1r = a[6] - a[22];
+    x1i = a[7] - a[23];
+    x2r = a[14] + a[30];
+    x2i = a[15] + a[31];
+    x3r = a[14] - a[30];
+    x3i = a[15] - a[31];
+    y3r = x0r + x2r;
+    y3i = x0i + x2i;
+    y7r = x0r - x2r;
+    y7i = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    y11r = wk1i * x0r - wk1r * x0i;
+    y11i = wk1i * x0i + wk1r * x0r;
+    x0r = x1r + x3i;
+    x0i = x1i - x3r;
+    y15r = wk1r * x0r - wk1i * x0i;
+    y15i = wk1r * x0i + wk1i * x0r;
+    x0r = y12r - y14r;
+    x0i = y12i - y14i;
+    x1r = y12r + y14r;
+    x1i = y12i + y14i;
+    x2r = y13r - y15r;
+    x2i = y13i - y15i;
+    x3r = y13r + y15r;
+    x3i = y13i + y15i;
+    a[24] = x0r + x2r;
+    a[25] = x0i + x2i;
+    a[26] = x0r - x2r;
+    a[27] = x0i - x2i;
+    a[28] = x1r - x3i;
+    a[29] = x1i + x3r;
+    a[30] = x1r + x3i;
+    a[31] = x1i - x3r;
+    x0r = y8r + y10r;
+    x0i = y8i + y10i;
+    x1r = y8r - y10r;
+    x1i = y8i - y10i;
+    x2r = y9r + y11r;
+    x2i = y9i + y11i;
+    x3r = y9r - y11r;
+    x3i = y9i - y11i;
+    a[16] = x0r + x2r;
+    a[17] = x0i + x2i;
+    a[18] = x0r - x2r;
+    a[19] = x0i - x2i;
+    a[20] = x1r - x3i;
+    a[21] = x1i + x3r;
+    a[22] = x1r + x3i;
+    a[23] = x1i - x3r;
+    x0r = y5r - y7i;
+    x0i = y5i + y7r;
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    x0r = y5r + y7i;
+    x0i = y5i - y7r;
+    x3r = wn4r * (x0r - x0i);
+    x3i = wn4r * (x0i + x0r);
+    x0r = y4r - y6i;
+    x0i = y4i + y6r;
+    x1r = y4r + y6i;
+    x1i = y4i - y6r;
+    a[8] = x0r + x2r;
+    a[9] = x0i + x2i;
+    a[10] = x0r - x2r;
+    a[11] = x0i - x2i;
+    a[12] = x1r - x3i;
+    a[13] = x1i + x3r;
+    a[14] = x1r + x3i;
+    a[15] = x1i - x3r;
+    x0r = y0r + y2r;
+    x0i = y0i + y2i;
+    x1r = y0r - y2r;
+    x1i = y0i - y2i;
+    x2r = y1r + y3r;
+    x2i = y1i + y3i;
+    x3r = y1r - y3r;
+    x3i = y1i - y3i;
+    a[0] = x0r + x2r;
+    a[1] = x0i + x2i;
+    a[2] = x0r - x2r;
+    a[3] = x0i - x2i;
+    a[4] = x1r - x3i;
+    a[5] = x1i + x3r;
+    a[6] = x1r + x3i;
+    a[7] = x1i - x3r;
+}
+
+
+void cftf162(double *a, double *w)
+{
+    double wn4r, wk1r, wk1i, wk2r, wk2i, wk3r, wk3i,
+           x0r, x0i, x1r, x1i, x2r, x2i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
+           y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i,
+           y8r, y8i, y9r, y9i, y10r, y10i, y11r, y11i,
+           y12r, y12i, y13r, y13i, y14r, y14i, y15r, y15i;
+
+    wn4r = w[1];
+    wk1r = w[4];
+    wk1i = w[5];
+    wk3r = w[6];
+    wk3i = -w[7];
+    wk2r = w[8];
+    wk2i = w[9];
+    x1r = a[0] - a[17];
+    x1i = a[1] + a[16];
+    x0r = a[8] - a[25];
+    x0i = a[9] + a[24];
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    y0r = x1r + x2r;
+    y0i = x1i + x2i;
+    y4r = x1r - x2r;
+    y4i = x1i - x2i;
+    x1r = a[0] + a[17];
+    x1i = a[1] - a[16];
+    x0r = a[8] + a[25];
+    x0i = a[9] - a[24];
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    y8r = x1r - x2i;
+    y8i = x1i + x2r;
+    y12r = x1r + x2i;
+    y12i = x1i - x2r;
+    x0r = a[2] - a[19];
+    x0i = a[3] + a[18];
+    x1r = wk1r * x0r - wk1i * x0i;
+    x1i = wk1r * x0i + wk1i * x0r;
+    x0r = a[10] - a[27];
+    x0i = a[11] + a[26];
+    x2r = wk3i * x0r - wk3r * x0i;
+    x2i = wk3i * x0i + wk3r * x0r;
+    y1r = x1r + x2r;
+    y1i = x1i + x2i;
+    y5r = x1r - x2r;
+    y5i = x1i - x2i;
+    x0r = a[2] + a[19];
+    x0i = a[3] - a[18];
+    x1r = wk3r * x0r - wk3i * x0i;
+    x1i = wk3r * x0i + wk3i * x0r;
+    x0r = a[10] + a[27];
+    x0i = a[11] - a[26];
+    x2r = wk1r * x0r + wk1i * x0i;
+    x2i = wk1r * x0i - wk1i * x0r;
+    y9r = x1r - x2r;
+    y9i = x1i - x2i;
+    y13r = x1r + x2r;
+    y13i = x1i + x2i;
+    x0r = a[4] - a[21];
+    x0i = a[5] + a[20];
+    x1r = wk2r * x0r - wk2i * x0i;
+    x1i = wk2r * x0i + wk2i * x0r;
+    x0r = a[12] - a[29];
+    x0i = a[13] + a[28];
+    x2r = wk2i * x0r - wk2r * x0i;
+    x2i = wk2i * x0i + wk2r * x0r;
+    y2r = x1r + x2r;
+    y2i = x1i + x2i;
+    y6r = x1r - x2r;
+    y6i = x1i - x2i;
+    x0r = a[4] + a[21];
+    x0i = a[5] - a[20];
+    x1r = wk2i * x0r - wk2r * x0i;
+    x1i = wk2i * x0i + wk2r * x0r;
+    x0r = a[12] + a[29];
+    x0i = a[13] - a[28];
+    x2r = wk2r * x0r - wk2i * x0i;
+    x2i = wk2r * x0i + wk2i * x0r;
+    y10r = x1r - x2r;
+    y10i = x1i - x2i;
+    y14r = x1r + x2r;
+    y14i = x1i + x2i;
+    x0r = a[6] - a[23];
+    x0i = a[7] + a[22];
+    x1r = wk3r * x0r - wk3i * x0i;
+    x1i = wk3r * x0i + wk3i * x0r;
+    x0r = a[14] - a[31];
+    x0i = a[15] + a[30];
+    x2r = wk1i * x0r - wk1r * x0i;
+    x2i = wk1i * x0i + wk1r * x0r;
+    y3r = x1r + x2r;
+    y3i = x1i + x2i;
+    y7r = x1r - x2r;
+    y7i = x1i - x2i;
+    x0r = a[6] + a[23];
+    x0i = a[7] - a[22];
+    x1r = wk1i * x0r + wk1r * x0i;
+    x1i = wk1i * x0i - wk1r * x0r;
+    x0r = a[14] + a[31];
+    x0i = a[15] - a[30];
+    x2r = wk3i * x0r - wk3r * x0i;
+    x2i = wk3i * x0i + wk3r * x0r;
+    y11r = x1r + x2r;
+    y11i = x1i + x2i;
+    y15r = x1r - x2r;
+    y15i = x1i - x2i;
+    x1r = y0r + y2r;
+    x1i = y0i + y2i;
+    x2r = y1r + y3r;
+    x2i = y1i + y3i;
+    a[0] = x1r + x2r;
+    a[1] = x1i + x2i;
+    a[2] = x1r - x2r;
+    a[3] = x1i - x2i;
+    x1r = y0r - y2r;
+    x1i = y0i - y2i;
+    x2r = y1r - y3r;
+    x2i = y1i - y3i;
+    a[4] = x1r - x2i;
+    a[5] = x1i + x2r;
+    a[6] = x1r + x2i;
+    a[7] = x1i - x2r;
+    x1r = y4r - y6i;
+    x1i = y4i + y6r;
+    x0r = y5r - y7i;
+    x0i = y5i + y7r;
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    a[8] = x1r + x2r;
+    a[9] = x1i + x2i;
+    a[10] = x1r - x2r;
+    a[11] = x1i - x2i;
+    x1r = y4r + y6i;
+    x1i = y4i - y6r;
+    x0r = y5r + y7i;
+    x0i = y5i - y7r;
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    a[12] = x1r - x2i;
+    a[13] = x1i + x2r;
+    a[14] = x1r + x2i;
+    a[15] = x1i - x2r;
+    x1r = y8r + y10r;
+    x1i = y8i + y10i;
+    x2r = y9r - y11r;
+    x2i = y9i - y11i;
+    a[16] = x1r + x2r;
+    a[17] = x1i + x2i;
+    a[18] = x1r - x2r;
+    a[19] = x1i - x2i;
+    x1r = y8r - y10r;
+    x1i = y8i - y10i;
+    x2r = y9r + y11r;
+    x2i = y9i + y11i;
+    a[20] = x1r - x2i;
+    a[21] = x1i + x2r;
+    a[22] = x1r + x2i;
+    a[23] = x1i - x2r;
+    x1r = y12r - y14i;
+    x1i = y12i + y14r;
+    x0r = y13r + y15i;
+    x0i = y13i - y15r;
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    a[24] = x1r + x2r;
+    a[25] = x1i + x2i;
+    a[26] = x1r - x2r;
+    a[27] = x1i - x2i;
+    x1r = y12r + y14i;
+    x1i = y12i - y14r;
+    x0r = y13r - y15i;
+    x0i = y13i + y15r;
+    x2r = wn4r * (x0r - x0i);
+    x2i = wn4r * (x0i + x0r);
+    a[28] = x1r - x2i;
+    a[29] = x1i + x2r;
+    a[30] = x1r + x2i;
+    a[31] = x1i - x2r;
+}
+
+
+void cftf081(double *a, double *w)
+{
+    double wn4r, x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
+           y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
+
+    wn4r = w[1];
+    x0r = a[0] + a[8];
+    x0i = a[1] + a[9];
+    x1r = a[0] - a[8];
+    x1i = a[1] - a[9];
+    x2r = a[4] + a[12];
+    x2i = a[5] + a[13];
+    x3r = a[4] - a[12];
+    x3i = a[5] - a[13];
+    y0r = x0r + x2r;
+    y0i = x0i + x2i;
+    y2r = x0r - x2r;
+    y2i = x0i - x2i;
+    y1r = x1r - x3i;
+    y1i = x1i + x3r;
+    y3r = x1r + x3i;
+    y3i = x1i - x3r;
+    x0r = a[2] + a[10];
+    x0i = a[3] + a[11];
+    x1r = a[2] - a[10];
+    x1i = a[3] - a[11];
+    x2r = a[6] + a[14];
+    x2i = a[7] + a[15];
+    x3r = a[6] - a[14];
+    x3i = a[7] - a[15];
+    y4r = x0r + x2r;
+    y4i = x0i + x2i;
+    y6r = x0r - x2r;
+    y6i = x0i - x2i;
+    x0r = x1r - x3i;
+    x0i = x1i + x3r;
+    x2r = x1r + x3i;
+    x2i = x1i - x3r;
+    y5r = wn4r * (x0r - x0i);
+    y5i = wn4r * (x0r + x0i);
+    y7r = wn4r * (x2r - x2i);
+    y7i = wn4r * (x2r + x2i);
+    a[8] = y1r + y5r;
+    a[9] = y1i + y5i;
+    a[10] = y1r - y5r;
+    a[11] = y1i - y5i;
+    a[12] = y3r - y7i;
+    a[13] = y3i + y7r;
+    a[14] = y3r + y7i;
+    a[15] = y3i - y7r;
+    a[0] = y0r + y4r;
+    a[1] = y0i + y4i;
+    a[2] = y0r - y4r;
+    a[3] = y0i - y4i;
+    a[4] = y2r - y6i;
+    a[5] = y2i + y6r;
+    a[6] = y2r + y6i;
+    a[7] = y2i - y6r;
+}
+
+
+void cftf082(double *a, double *w)
+{
+    double wn4r, wk1r, wk1i, x0r, x0i, x1r, x1i,
+           y0r, y0i, y1r, y1i, y2r, y2i, y3r, y3i,
+           y4r, y4i, y5r, y5i, y6r, y6i, y7r, y7i;
+
+    wn4r = w[1];
+    wk1r = w[2];
+    wk1i = w[3];
+    y0r = a[0] - a[9];
+    y0i = a[1] + a[8];
+    y1r = a[0] + a[9];
+    y1i = a[1] - a[8];
+    x0r = a[4] - a[13];
+    x0i = a[5] + a[12];
+    y2r = wn4r * (x0r - x0i);
+    y2i = wn4r * (x0i + x0r);
+    x0r = a[4] + a[13];
+    x0i = a[5] - a[12];
+    y3r = wn4r * (x0r - x0i);
+    y3i = wn4r * (x0i + x0r);
+    x0r = a[2] - a[11];
+    x0i = a[3] + a[10];
+    y4r = wk1r * x0r - wk1i * x0i;
+    y4i = wk1r * x0i + wk1i * x0r;
+    x0r = a[2] + a[11];
+    x0i = a[3] - a[10];
+    y5r = wk1i * x0r - wk1r * x0i;
+    y5i = wk1i * x0i + wk1r * x0r;
+    x0r = a[6] - a[15];
+    x0i = a[7] + a[14];
+    y6r = wk1i * x0r - wk1r * x0i;
+    y6i = wk1i * x0i + wk1r * x0r;
+    x0r = a[6] + a[15];
+    x0i = a[7] - a[14];
+    y7r = wk1r * x0r - wk1i * x0i;
+    y7i = wk1r * x0i + wk1i * x0r;
+    x0r = y0r + y2r;
+    x0i = y0i + y2i;
+    x1r = y4r + y6r;
+    x1i = y4i + y6i;
+    a[0] = x0r + x1r;
+    a[1] = x0i + x1i;
+    a[2] = x0r - x1r;
+    a[3] = x0i - x1i;
+    x0r = y0r - y2r;
+    x0i = y0i - y2i;
+    x1r = y4r - y6r;
+    x1i = y4i - y6i;
+    a[4] = x0r - x1i;
+    a[5] = x0i + x1r;
+    a[6] = x0r + x1i;
+    a[7] = x0i - x1r;
+    x0r = y1r - y3i;
+    x0i = y1i + y3r;
+    x1r = y5r - y7r;
+    x1i = y5i - y7i;
+    a[8] = x0r + x1r;
+    a[9] = x0i + x1i;
+    a[10] = x0r - x1r;
+    a[11] = x0i - x1i;
+    x0r = y1r + y3i;
+    x0i = y1i - y3r;
+    x1r = y5r + y7r;
+    x1i = y5i + y7i;
+    a[12] = x0r - x1i;
+    a[13] = x0i + x1r;
+    a[14] = x0r + x1i;
+    a[15] = x0i - x1r;
+}
+
+
+void cftf040(double *a)
+{
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+    x0r = a[0] + a[4];
+    x0i = a[1] + a[5];
+    x1r = a[0] - a[4];
+    x1i = a[1] - a[5];
+    x2r = a[2] + a[6];
+    x2i = a[3] + a[7];
+    x3r = a[2] - a[6];
+    x3i = a[3] - a[7];
+    a[0] = x0r + x2r;
+    a[1] = x0i + x2i;
+    a[2] = x1r - x3i;
+    a[3] = x1i + x3r;
+    a[4] = x0r - x2r;
+    a[5] = x0i - x2i;
+    a[6] = x1r + x3i;
+    a[7] = x1i - x3r;
+}
+
+
+void cftb040(double *a)
+{
+    double x0r, x0i, x1r, x1i, x2r, x2i, x3r, x3i;
+
+    x0r = a[0] + a[4];
+    x0i = a[1] + a[5];
+    x1r = a[0] - a[4];
+    x1i = a[1] - a[5];
+    x2r = a[2] + a[6];
+    x2i = a[3] + a[7];
+    x3r = a[2] - a[6];
+    x3i = a[3] - a[7];
+    a[0] = x0r + x2r;
+    a[1] = x0i + x2i;
+    a[2] = x1r + x3i;
+    a[3] = x1i - x3r;
+    a[4] = x0r - x2r;
+    a[5] = x0i - x2i;
+    a[6] = x1r - x3i;
+    a[7] = x1i + x3r;
+}
+
+
+void cftx020(double *a)
+{
+    double x0r, x0i;
+
+    x0r = a[0] - a[2];
+    x0i = a[1] - a[3];
+    a[0] += a[2];
+    a[1] += a[3];
+    a[2] = x0r;
+    a[3] = x0i;
+}
+
+
+void rftfsub(int n, double *a, int nc, double *c)
+{
+    int j, k, kk, ks, m;
+    double wkr, wki, xr, xi, yr, yi;
+
+    m = n >> 1;
+    ks = 2 * nc / m;
+    kk = 0;
+    for (j = 2; j < m; j += 2)
+    {
+        k = n - j;
+        kk += ks;
+        wkr = 0.5 - c[nc - kk];
+        wki = c[kk];
+        xr = a[j] - a[k];
+        xi = a[j + 1] + a[k + 1];
+        yr = wkr * xr - wki * xi;
+        yi = wkr * xi + wki * xr;
+        a[j] -= yr;
+        a[j + 1] -= yi;
+        a[k] += yr;
+        a[k + 1] -= yi;
+    }
+}
+
+
+void rftbsub(int n, double *a, int nc, double *c)
+{
+    int j, k, kk, ks, m;
+    double wkr, wki, xr, xi, yr, yi;
+
+    m = n >> 1;
+    ks = 2 * nc / m;
+    kk = 0;
+    for (j = 2; j < m; j += 2)
+    {
+        k = n - j;
+        kk += ks;
+        wkr = 0.5 - c[nc - kk];
+        wki = c[kk];
+        xr = a[j] - a[k];
+        xi = a[j + 1] + a[k + 1];
+        yr = wkr * xr + wki * xi;
+        yi = wkr * xi - wki * xr;
+        a[j] -= yr;
+        a[j + 1] -= yi;
+        a[k] += yr;
+        a[k + 1] -= yi;
+    }
+}
+
+
+void dctsub(int n, double *a, int nc, double *c)
+{
+    int j, k, kk, ks, m;
+    double wkr, wki, xr;
+
+    m = n >> 1;
+    ks = nc / n;
+    kk = 0;
+    for (j = 1; j < m; j++)
+    {
+        k = n - j;
+        kk += ks;
+        wkr = c[kk] - c[nc - kk];
+        wki = c[kk] + c[nc - kk];
+        xr = wki * a[j] - wkr * a[k];
+        a[j] = wkr * a[j] + wki * a[k];
+        a[k] = xr;
+    }
+    a[m] *= c[0];
+}
+
+
+void dstsub(int n, double *a, int nc, double *c)
+{
+    int j, k, kk, ks, m;
+    double wkr, wki, xr;
+
+    m = n >> 1;
+    ks = nc / n;
+    kk = 0;
+    for (j = 1; j < m; j++)
+    {
+        k = n - j;
+        kk += ks;
+        wkr = c[kk] - c[nc - kk];
+        wki = c[kk] + c[nc - kk];
+        xr = wki * a[k] - wkr * a[j];
+        a[k] = wkr * a[k] + wki * a[j];
+        a[j] = xr;
+    }
+    a[m] *= c[0];
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fftsg.h	Mon Jan 07 16:27:15 2013 +0000
@@ -0,0 +1,21 @@
+/* FFT functions */
+void cdft(int n, int isgn, double *a, int *ip, double *w);
+void rdft(int n, int isgn, double *a, int *ip, double *w);
+void ddct(int n, int isgn, double *a, int *ip, double *w);
+void ddst(int n, int isgn, double *a, int *ip, double *w);
+void dfct(int n, double *a, double *t, int *ip, double *w);
+void dfst(int n, double *a, double *t, int *ip, double *w);
+
+/* Auxiliary functions */
+void makewt(int nw, int *ip, double *w);
+void bitrv2(int n, int *ip, double *a);
+void bitrv2conj(int n, int *ip, double *a);
+void cftfsub(int n, double *a, double *w);
+void cftbsub(int n, double *a, double *w);
+void makect(int nc, int *ip, double *c);
+void rftfsub(int n, double *a, int nc, double *c);
+void rftbsub(int n, double *a, int nc, double *c);
+void dctsub(int n, double *a, int nc, double *c);
+void dstsub(int n, double *a, int nc, double *c);
+void cft1st(int n, double *a, double *w);
+void cftmdl(int n, int l, double *a, double *w);
--- a/src/fini.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/fini.c	Mon Jan 07 16:27:15 2013 +0000
@@ -14,17 +14,13 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
 /* fini.c: Contains library destructor routine */
 
-#ifdef XTRACT_FFT
-#include <fftw3.h>
-//#include "xtract_globals_private.h"
 #include "xtract/libxtract.h"
-#endif
 
 #ifdef __GNUC__
 __attribute__((destructor)) void fini()
@@ -32,10 +28,7 @@
 void _fini()
 #endif
 {
-#ifdef XTRACT_FFT
-xtract_free_fft();
-fftwf_cleanup();
-#endif
+    xtract_free_fft();
 }
 
 
--- a/src/helper.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/helper.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -33,7 +33,8 @@
 #define INDEX 1
 #endif
 
-int xtract_windowed(const float *data, const int N, const void *argv, float *result){
+int xtract_windowed(const float *data, const int N, const void *argv, float *result)
+{
 
     int n;
     const float *window;
@@ -48,7 +49,8 @@
 
 }
 
-int xtract_features_from_subframes(const float *data, const int N, const int feature, const void *argv, float *result){
+int xtract_features_from_subframes(const float *data, const int N, const int feature, const void *argv, float *result)
+{
 
     const float *frame1,
           *frame2;
@@ -73,7 +75,8 @@
 
 }
 
-inline int xtract_is_denormal(double const d){
+inline int xtract_is_denormal(double const d)
+{
     if(sizeof(d) != 2 * sizeof(int))
         fprintf(stderr, "libxtract: Error: xtract_is_denormal() detects inconsistent wordlength for type 'double'\n");
 
@@ -81,3 +84,8 @@
     return (l&0x7ff00000) == 0 && d!=0; //Check for 0 may not be necessary
 }
 
+inline bool xtract_is_poweroftwo(unsigned int x)
+{
+    return ((x != 0) && !(x & (x - 1)));
+}
+
--- a/src/init.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/init.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -26,41 +26,38 @@
 
 #include <math.h>
 #include <stdlib.h>
+#include <stdio.h>
+
+#include "fftsg.h"
 
 #include "xtract/libxtract.h"
 #include "xtract_window_private.h"
 #define DEFINE_GLOBALS
 #include "xtract_globals_private.h"
 
-#ifdef XTRACT_FFT
-#include <fftw3.h>
 
-#ifndef XTRACT_FFT_OPTIMISATION_LEVEL
-/* This should never happen */
-#define XTRACT_FFT_OPTIMISATION_LEVEL 1
-#endif
+int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables)
+{
 
-int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables){
-
-    int n, i, k, *fft_peak, M, next_peak; 
-    float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, 
+    int n, i, k, *fft_peak, M, next_peak;
+    float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
           freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
 
     mel_peak = height_norm = lin_peak = NULL;
     fft_peak = NULL;
-    norm = 1; 
+    norm = 1;
 
     mel_freq_max = 1127 * log(1 + freq_max / 700);
     mel_freq_min = 1127 * log(1 + freq_min / 700);
     freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
 
-    mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float)); 
+    mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
     /* +2 for zeros at start and end */
     lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
     fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
     height_norm = (float *)malloc(freq_bands * sizeof(float));
 
-    if(mel_peak == NULL || height_norm == NULL || 
+    if(mel_peak == NULL || height_norm == NULL ||
             lin_peak == NULL || fft_peak == NULL)
         return XTRACT_MALLOC_FAILED;
 
@@ -71,20 +68,24 @@
     fft_peak[0] = lin_peak[0] / nyquist * M;
 
 
-    for (n = 1; n < freq_bands + 2; n++){	
-        //roll out peak locations - mel, linear and linear on fft window scale 
+    for (n = 1; n < freq_bands + 2; n++)
+    {
+        //roll out peak locations - mel, linear and linear on fft window scale
         mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
         lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
         fft_peak[n] = lin_peak[n] / nyquist * M;
     }
 
-    for (n = 0; n < freq_bands; n++){
+    for (n = 0; n < freq_bands; n++)
+    {
         //roll out normalised gain of each peak
-        if (style == XTRACT_EQUAL_GAIN){
-            height = 1;	
+        if (style == XTRACT_EQUAL_GAIN)
+        {
+            height = 1;
             norm_fact = norm;
         }
-        else{
+        else
+        {
             height = 2 / (lin_peak[n + 2] - lin_peak[n]);
             norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
         }
@@ -93,21 +94,23 @@
 
     i = 0;
 
-    for(n = 0; n < freq_bands; n++){
+    for(n = 0; n < freq_bands; n++)
+    {
 
         // calculate the rise increment
         if(n==0)
             inc = height_norm[n] / fft_peak[n];
         else
             inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
-        val = 0;	
+        val = 0;
 
         // zero the start of the array
         for(k = 0; k < i; k++)
             fft_tables[n][k] = 0.f;
 
         // fill in the rise
-        for(; i <= fft_peak[n]; i++){ 
+        for(; i <= fft_peak[n]; i++)
+        {
             fft_tables[n][i] = val;
             val += inc;
         }
@@ -118,8 +121,9 @@
         val = 0;
         next_peak = fft_peak[n + 1];
 
-        // reverse fill the 'fall' 
-        for(i = next_peak; i > fft_peak[n]; i--){ 
+        // reverse fill the 'fall'
+        for(i = next_peak; i > fft_peak[n]; i--)
+        {
             fft_tables[n][i] = val;
             val += inc;
         }
@@ -131,7 +135,10 @@
 
 
     /* Initialise the fft_plan for the DCT */
+    /*
+     * Ooura doesn't support non power-of-two DCT
     xtract_init_fft(freq_bands, XTRACT_MFCC);
+    */
 
     free(mel_peak);
     free(lin_peak);
@@ -142,82 +149,95 @@
 
 }
 
-int xtract_init_fft(int N, int feature_name){
+void xtract_init_ooura(xtract_ooura_data *ooura_data, unsigned int N)
+{
+    ooura_data->ooura_ip  = (int *)calloc((2 + sqrt(N)), sizeof(int));
+    ooura_data->ooura_w   = (double *)calloc((N - 1), sizeof(double));
+    ooura_data->initialised = true;
+}
 
-    float *input, *output;
-    int optimisation;
+void xtract_free_ooura(xtract_ooura_data *ooura_data)
+{
+    free(ooura_data->ooura_ip);
+    free(ooura_data->ooura_w);
+    ooura_data->ooura_ip = NULL;
+    ooura_data->ooura_w = NULL;
+    ooura_data->initialised = false;
+}
 
-    input = output = NULL;
+int xtract_init_fft(int N, int feature_name)
+{
 
-    //fprintf(stderr, "Optimisation level: %d\n", XTRACT_FFT_OPTIMISATION_LEVEL);
+    int M = N >> 1;
 
-    if(XTRACT_FFT_OPTIMISATION_LEVEL == 0)
-        optimisation = FFTW_ESTIMATE;
-    else if(XTRACT_FFT_OPTIMISATION_LEVEL == 1)
-        optimisation = FFTW_MEASURE;
-    else if(XTRACT_FFT_OPTIMISATION_LEVEL == 2)
-        optimisation = FFTW_PATIENT;
-    else
-        optimisation = FFTW_MEASURE; /* The default */
+    if(!xtract_is_poweroftwo(N))
+    {
+        fprintf(stderr,
+            "libxtract: error: only power-of-two FFT sizes are supported.\n");
+		exit(EXIT_FAILURE);
+    }
 
     if(feature_name == XTRACT_AUTOCORRELATION_FFT)
-        N <<= 1;
-
-    input = malloc(N * sizeof(float));
-    output = malloc(N * sizeof(float));
-
-    switch(feature_name){
-        case XTRACT_SPECTRUM:
-            if(fft_plans.spectrum_plan != NULL)
-                fftwf_destroy_plan(fft_plans.spectrum_plan);
-            fft_plans.spectrum_plan = 
-                fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
-            break;
-        case XTRACT_AUTOCORRELATION_FFT:
-            if(fft_plans.autocorrelation_fft_plan_1 != NULL)
-                fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_1);
-            if(fft_plans.autocorrelation_fft_plan_2 != NULL)
-                fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_2);
-            fft_plans.autocorrelation_fft_plan_1 =
-                fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
-            fft_plans.autocorrelation_fft_plan_2 =
-                fftwf_plan_r2r_1d(N, input, output, FFTW_HC2R, optimisation);
-            break;
-        case XTRACT_DCT:
-            if(fft_plans.dct_plan != NULL)
-                fftwf_destroy_plan(fft_plans.dct_plan);
-            fft_plans.dct_plan =
-                fftwf_plan_r2r_1d(N, input, output, FFTW_REDFT10, optimisation);
-        case XTRACT_MFCC:
-            if(fft_plans.dct_plan != NULL)
-                fftwf_destroy_plan(fft_plans.dct_plan);
-            fft_plans.dct_plan =
-                fftwf_plan_r2r_1d(N, output, output, FFTW_REDFT00, optimisation);
-            break;
+    {
+        M = N; /* allow for zero padding */
     }
 
-    free(input);
-    free(output);
+    switch(feature_name)
+    {
+    case XTRACT_SPECTRUM:
+        if(ooura_data_spectrum.initialised)
+        {
+            xtract_free_ooura(&ooura_data_spectrum);
+        }
+        xtract_init_ooura(&ooura_data_spectrum, M);
+        break;
+    case XTRACT_AUTOCORRELATION_FFT:
+        if(ooura_data_autocorrelation_fft.initialised)
+        {
+            xtract_free_ooura(&ooura_data_autocorrelation_fft);
+        }
+        xtract_init_ooura(&ooura_data_autocorrelation_fft, M);
+        break;
+    case XTRACT_DCT:
+        if(ooura_data_dct.initialised)
+        {
+            xtract_free_ooura(&ooura_data_dct);
+        }
+        xtract_init_ooura(&ooura_data_dct, M);
+    case XTRACT_MFCC:
+        if(ooura_data_mfcc.initialised)
+        {
+            xtract_free_ooura(&ooura_data_mfcc);
+        }
+        xtract_init_ooura(&ooura_data_mfcc, M);
+        break;
+    }
 
     return XTRACT_SUCCESS;
-
 }
 
-void xtract_free_fft(void){
-    if(fft_plans.spectrum_plan != NULL)
-        fftwf_destroy_plan(fft_plans.spectrum_plan);
-    if(fft_plans.autocorrelation_fft_plan_1 != NULL)
-        fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_1);
-    if(fft_plans.autocorrelation_fft_plan_2 != NULL)
-        fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_2);
-    if(fft_plans.dct_plan != NULL)
-        fftwf_destroy_plan(fft_plans.dct_plan);
-//    fftwf_cleanup();
+void xtract_free_fft(void)
+{
+    if(ooura_data_spectrum.initialised)
+    {
+        xtract_free_ooura(&ooura_data_spectrum);
+    }
+    if(ooura_data_autocorrelation_fft.initialised)
+    {
+        xtract_free_ooura(&ooura_data_autocorrelation_fft);
+    }
+    if(ooura_data_dct.initialised)
+    {
+        xtract_free_ooura(&ooura_data_dct);
+    }
+    if(ooura_data_mfcc.initialised)
+    {
+        xtract_free_ooura(&ooura_data_mfcc);
+    }
 }
 
-#endif
-
-int xtract_init_bark(int N, float sr, int *band_limits){
+int xtract_init_bark(int N, float sr, int *band_limits)
+{
 
     float  edges[] = {0, 100, 200, 300, 400, 510, 630, 770, 920, 1080, 1270, 1480, 1720, 2000, 2320, 2700, 3150, 3700, 4400, 5300, 6400, 7700, 9500, 12000, 15500, 20500, 27000}; /* Takes us up to sr = 54kHz (CCRMA: JOS)*/
 
@@ -230,65 +250,62 @@
     return XTRACT_SUCCESS;
 }
 
-float *xtract_init_window(const int N, const int type){
-
+float *xtract_init_window(const int N, const int type)
+{
     float *window;
 
     window = malloc(N * sizeof(float));
 
-    switch (type) {
-        case XTRACT_GAUSS:
-            gauss(window, N, 0.4);
-            break;
-        case XTRACT_HAMMING:
-            hamming(window, N);
-            break;
-        case XTRACT_HANN:
-            hann(window, N);
-            break;
-        case XTRACT_BARTLETT:
-            bartlett(window, N);
-            break;
-        case XTRACT_TRIANGULAR:
-            triangular(window, N);
-            break;
-        case XTRACT_BARTLETT_HANN:
-            bartlett_hann(window, N);
-            break;
-        case XTRACT_BLACKMAN:
-            blackman(window, N);
-            break;
-        case XTRACT_KAISER:
-            kaiser(window, N, 3 * PI);
-            break;
-        case XTRACT_BLACKMAN_HARRIS:
-            blackman_harris(window, N);
-            break;
-        default:
-            hann(window, N);
-            break;
+    switch (type)
+    {
+    case XTRACT_GAUSS:
+        gauss(window, N, 0.4);
+        break;
+    case XTRACT_HAMMING:
+        hamming(window, N);
+        break;
+    case XTRACT_HANN:
+        hann(window, N);
+        break;
+    case XTRACT_BARTLETT:
+        bartlett(window, N);
+        break;
+    case XTRACT_TRIANGULAR:
+        triangular(window, N);
+        break;
+    case XTRACT_BARTLETT_HANN:
+        bartlett_hann(window, N);
+        break;
+    case XTRACT_BLACKMAN:
+        blackman(window, N);
+        break;
+    case XTRACT_KAISER:
+        kaiser(window, N, 3 * PI);
+        break;
+    case XTRACT_BLACKMAN_HARRIS:
+        blackman_harris(window, N);
+        break;
+    default:
+        hann(window, N);
+        break;
     }
 
     return window;
-
 }
 
-void xtract_free_window(float *window){
-
+void xtract_free_window(float *window)
+{
     free(window);
-
 }
 
 #ifdef __GNUC__
 __attribute__((constructor)) void init()
 #else
-    void _init()·
+void _init()·
 #endif
 {
-#ifdef XTRACT_FFT
-    fft_plans.spectrum_plan = NULL;
-    fft_plans.autocorrelation_fft_plan_1 = NULL;
-    fft_plans.autocorrelation_fft_plan_2 = NULL;
-    fft_plans.dct_plan = NULL;
-#endif
+    ooura_data_dct.initialised = false;
+    ooura_data_spectrum.initialised = false;
+    ooura_data_autocorrelation_fft.initialised = false;
+    ooura_data_mfcc.initialised = false;
 }
--- a/src/libxtract.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/libxtract.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -22,7 +22,8 @@
 #include "xtract/libxtract.h"
 #define XTRACT_H
 
-int(*xtract[])(const float *, const int, const void *, float *) = {
+int(*xtract[])(const float *, const int, const void *, float *) =
+{
     /* xtract_scalar.h */
     xtract_mean,
     xtract_variance,
--- a/src/scalar.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/scalar.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -33,79 +33,85 @@
 #include "xtract_macros_private.h"
 
 #ifndef powf
-    #define powf pow
+#define powf pow
 #endif
 
 #ifndef expf
-    #define expf exp
+#define expf exp
 #endif
 
 #ifndef sqrtf
-    #define sqrtf sqrt
+#define sqrtf sqrt
 #endif
 
 #ifndef fabsf
-    #define fabsf fabs
+#define fabsf fabs
 #endif
 
 
-void test(void){
+void test(void)
+{
     printf("Hello world\n");
 #ifdef WORDS_BIGENDIAN
     printf("Big endian!\n");
 #endif
 }
 
-int xtract_mean(const float *data, const int N, const void *argv, float *result){
-
-    int n = N;
-    
-    *result = 0.f;
-
-    while(n--)
-	*result += data[n];
-    
-    *result /= N;
-
-    return XTRACT_SUCCESS;
-}
-
-int xtract_variance(const float *data, const int N, const void *argv, float *result){
+int xtract_mean(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     *result = 0.f;
 
     while(n--)
-	*result += powf(data[n] - *(float *)argv, 2);
+        *result += data[n];
+
+    *result /= N;
+
+    return XTRACT_SUCCESS;
+}
+
+int xtract_variance(const float *data, const int N, const void *argv, float *result)
+{
+
+    int n = N;
+
+    *result = 0.f;
+
+    while(n--)
+        *result += powf(data[n] - *(float *)argv, 2);
 
     *result = *result / (N - 1);
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_standard_deviation(const float *data, const int N, const void *argv, float *result){
+int xtract_standard_deviation(const float *data, const int N, const void *argv, float *result)
+{
 
     *result = sqrtf(*(float *)argv);
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_average_deviation(const float *data, const int N, const void *argv, float *result){
+int xtract_average_deviation(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     *result = 0.f;
 
     while(n--)
-	*result += fabsf(data[n] - *(float *)argv);
+        *result += fabsf(data[n] - *(float *)argv);
 
     *result /= N;
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_skewness(const float *data, const int N, const void *argv,  float *result){
+int xtract_skewness(const float *data, const int N, const void *argv,  float *result)
+{
 
     int n = N;
 
@@ -113,9 +119,10 @@
 
     *result = 0.f;
 
-    while(n--){
-	temp = (data[n] - ((float *)argv)[0]) / ((float *)argv)[1];
-	*result += powf(temp, 3);
+    while(n--)
+    {
+        temp = (data[n] - ((float *)argv)[0]) / ((float *)argv)[1];
+        *result += powf(temp, 3);
     }
 
     *result /= N;
@@ -124,7 +131,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_kurtosis(const float *data, const int N, const void *argv,  float *result){
+int xtract_kurtosis(const float *data, const int N, const void *argv,  float *result)
+{
 
     int n = N;
 
@@ -132,9 +140,10 @@
 
     *result = 0.f;
 
-    while(n--){
-	temp = (data[n] - ((float *)argv)[0]) / ((float *)argv)[1];
-	*result += powf(temp, 4);
+    while(n--)
+    {
+        temp = (data[n] - ((float *)argv)[0]) / ((float *)argv)[1];
+        *result += powf(temp, 4);
     }
 
     *result /= N;
@@ -143,7 +152,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spectral_centroid(const float *data, const int N, const void *argv,  float *result){
+int xtract_spectral_centroid(const float *data, const int N, const void *argv,  float *result)
+{
 
     int n = (N >> 1);
 
@@ -153,9 +163,10 @@
     amps = data;
     freqs = data + n;
 
-    while(n--){
-	FA += freqs[n] * amps[n];
-	A += amps[n];
+    while(n--)
+    {
+        FA += freqs[n] * amps[n];
+        A += amps[n];
     }
 
     if(A == 0.f)
@@ -166,13 +177,15 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spectral_mean(const float *data, const int N, const void *argv, float *result){
+int xtract_spectral_mean(const float *data, const int N, const void *argv, float *result)
+{
 
     return xtract_spectral_centroid(data, N, argv, result);
 
 }
 
-int xtract_spectral_variance(const float *data, const int N, const void *argv, float *result){
+int xtract_spectral_variance(const float *data, const int N, const void *argv, float *result)
+{
 
     int m;
     float A = 0.f;
@@ -185,7 +198,8 @@
 
     *result = 0.f;
 
-    while(m--){
+    while(m--)
+    {
         A += amps[m];
         *result += powf(freqs[m] - ((float *)argv)[0], 2) * amps[m];
     }
@@ -195,9 +209,10 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spectral_standard_deviation(const float *data, const int N, const void *argv, float *result){
+int xtract_spectral_standard_deviation(const float *data, const int N, const void *argv, float *result)
+{
 
-    *result = sqrtf(*(float *)argv); 
+    *result = sqrtf(*(float *)argv);
 
     return XTRACT_SUCCESS;
 }
@@ -225,7 +240,8 @@
     return XTRACT_SUCCESS;
 }*/
 
-int xtract_spectral_skewness(const float *data, const int N, const void *argv,  float *result){
+int xtract_spectral_skewness(const float *data, const int N, const void *argv,  float *result)
+{
 
     int m;
     const float *freqs, *amps;
@@ -245,7 +261,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spectral_kurtosis(const float *data, const int N, const void *argv,  float *result){
+int xtract_spectral_kurtosis(const float *data, const int N, const void *argv,  float *result)
+{
 
     int m;
     const float *freqs, *amps;
@@ -266,28 +283,31 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_irregularity_k(const float *data, const int N, const void *argv, float *result){
+int xtract_irregularity_k(const float *data, const int N, const void *argv, float *result)
+{
 
     int n,
-	M = N - 1;
-	
+        M = N - 1;
+
     *result = 0.f;
-	
+
     for(n = 1; n < M; n++)
-	*result += fabsf(data[n] - (data[n-1] + data[n] + data[n+1]) / 3.f);
+        *result += fabsf(data[n] - (data[n-1] + data[n] + data[n+1]) / 3.f);
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result){
+int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     double num = 0.f, den = 0.f;
 
-    while(n--){
-	num += powf(data[n] - data[n+1], 2);
-	den += powf(data[n], 2);
+    while(n--)
+    {
+        num += powf(data[n] - data[n+1], 2);
+        den += powf(data[n], 2);
     }
 
     *result = (float)(num / den);
@@ -295,7 +315,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_tristimulus_1(const float *data, const int N, const void *argv, float *result){
+int xtract_tristimulus_1(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
@@ -303,25 +324,30 @@
 
     den = p1 = temp = 0.f;
 
-    for(n = 0; n < N; n++){
-	if((temp = data[n])){
-	    den += temp;
-	    if(!p1)
-		p1 = temp;
-	}
+    for(n = 0; n < N; n++)
+    {
+        if((temp = data[n]))
+        {
+            den += temp;
+            if(!p1)
+                p1 = temp;
+        }
     }
 
-    if(den == 0.f || p1 == 0.f){
+    if(den == 0.f || p1 == 0.f)
+    {
         *result = 0.f;
         return XTRACT_NO_RESULT;
     }
-    else{
+    else
+    {
         *result = p1 / den;
         return XTRACT_SUCCESS;
     }
 }
 
-int xtract_tristimulus_2(const float *data, const int N, const void *argv, float *result){
+int xtract_tristimulus_2(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
@@ -329,32 +355,37 @@
 
     den = p2 = p3 = p4 = ps = temp = 0.f;
 
-    for(n = 0; n < N; n++){
-	if((temp = data[n])){
-	    den += temp;
-	    if(!p2)
-		p2 = temp;
-	    else if(!p3)
-		p3 = temp;
-	    else if(!p4)
-		p4 = temp;
-	}
+    for(n = 0; n < N; n++)
+    {
+        if((temp = data[n]))
+        {
+            den += temp;
+            if(!p2)
+                p2 = temp;
+            else if(!p3)
+                p3 = temp;
+            else if(!p4)
+                p4 = temp;
+        }
     }
 
     ps = p2 + p3 + p4;
 
-    if(den == 0.f || ps == 0.f){
+    if(den == 0.f || ps == 0.f)
+    {
         *result = 0.f;
         return XTRACT_NO_RESULT;
     }
-    else{
+    else
+    {
         *result = ps / den;
         return XTRACT_SUCCESS;
     }
 
 }
 
-int xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result){
+int xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, count = 0;
 
@@ -362,26 +393,31 @@
 
     den = num = temp = 0.f;
 
-    for(n = 0; n < N; n++){
-	if((temp = data[n])){
-	    den += temp;
-	    if(count >= 5)
-		num += temp;
-	    count++;
-	}
+    for(n = 0; n < N; n++)
+    {
+        if((temp = data[n]))
+        {
+            den += temp;
+            if(count >= 5)
+                num += temp;
+            count++;
+        }
     }
 
-    if(den == 0.f || num == 0.f){
+    if(den == 0.f || num == 0.f)
+    {
         *result = 0.f;
         return XTRACT_NO_RESULT;
     }
-    else{
+    else
+    {
         *result = num / den;
         return XTRACT_SUCCESS;
     }
 }
 
-int xtract_smoothness(const float *data, const int N, const void *argv, float *result){
+int xtract_smoothness(const float *data, const int N, const void *argv, float *result)
+{
 
     int n, M;
 
@@ -390,18 +426,19 @@
     input = (float *)malloc(N * sizeof(float));
     memcpy(input, data, N * sizeof(float));
 
-    if (input[0] <= 0) 
+    if (input[0] <= 0)
         input[0] = XTRACT_LOG_LIMIT;
-    if (input[1] <= 0) 
+    if (input[1] <= 0)
         input[1] = XTRACT_LOG_LIMIT;
 
     M = N - 1;
 
-    for(n = 1; n < M; n++){ 
-	if(input[n+1] <= 0) 
+    for(n = 1; n < M; n++)
+    {
+        if(input[n+1] <= 0)
             input[n+1] = XTRACT_LOG_LIMIT;
-	*result += fabsf(20.f * logf(input[n]) - (20.f * logf(input[n-1]) + 
-		    20.f * logf(input[n]) + 20.f * logf(input[n+1])) / 3.f);
+        *result += fabsf(20.f * logf(input[n]) - (20.f * logf(input[n-1]) +
+                         20.f * logf(input[n]) + 20.f * logf(input[n+1])) / 3.f);
     }
 
     free(input);
@@ -409,24 +446,27 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spread(const float *data, const int N, const void *argv, float *result){
+int xtract_spread(const float *data, const int N, const void *argv, float *result)
+{
 
-      return xtract_spectral_variance(data, N, argv, result);
+    return xtract_spectral_variance(data, N, argv, result);
 }
 
-int xtract_zcr(const float *data, const int N, const void *argv, float *result){
+int xtract_zcr(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     for(n = 1; n < N; n++)
-	if(data[n] * data[n-1] < 0) (*result)++;
+        if(data[n] * data[n-1] < 0) (*result)++;
 
     *result /= (float)N;
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_rolloff(const float *data, const int N, const void *argv, float *result){
+int xtract_rolloff(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
     float pivot, temp, percentile;
@@ -434,12 +474,12 @@
     pivot = temp = 0.f;
     percentile = ((float *)argv)[1];
 
-    while(n--) pivot += data[n];   
+    while(n--) pivot += data[n];
 
     pivot *= percentile / 100.f;
 
     for(n = 0; temp < pivot; n++)
-	temp += data[n];
+        temp += data[n];
 
     *result = n * ((float *)argv)[0];
     /* *result = (n / (float)N) * (((float *)argv)[1] * .5); */
@@ -447,30 +487,33 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_loudness(const float *data, const int N, const void *argv, float *result){
+int xtract_loudness(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, rv;
 
     *result = 0.f;
 
-    if(n > XTRACT_BARK_BANDS){
-	n = XTRACT_BARK_BANDS; 
-	rv = XTRACT_BAD_VECTOR_SIZE; 
+    if(n > XTRACT_BARK_BANDS)
+    {
+        n = XTRACT_BARK_BANDS;
+        rv = XTRACT_BAD_VECTOR_SIZE;
     }
     else
-	rv = XTRACT_SUCCESS;
+        rv = XTRACT_SUCCESS;
 
     while(n--)
-	*result += powf(data[n], 0.23);
+        *result += powf(data[n], 0.23);
 
     return rv;
 }
 
-int xtract_flatness(const float *data, const int N, const void *argv, float *result){
+int xtract_flatness(const float *data, const int N, const void *argv, float *result)
+{
 
     int n, count, denormal_found;
 
-    double num, den, temp; 
+    double num, den, temp;
 
     num = 1.f;
     den = temp = 0.f;
@@ -478,9 +521,12 @@
     denormal_found = 0;
     count = 0;
 
-    for(n = 0; n < N; n++){
-        if((temp = data[n]) != 0.f) {
-            if (xtract_is_denormal(num)){
+    for(n = 0; n < N; n++)
+    {
+        if((temp = data[n]) != 0.f)
+        {
+            if (xtract_is_denormal(num))
+            {
                 denormal_found = 1;
                 break;
             }
@@ -490,7 +536,8 @@
         }
     }
 
-    if(!count){
+    if(!count)
+    {
         *result = 0.f;
         return XTRACT_NO_RESULT;
     }
@@ -505,16 +552,17 @@
         return XTRACT_DENORMAL_FOUND;
     else
         return XTRACT_SUCCESS;
-    
+
 }
 
-int xtract_flatness_db(const float *data, const int N, const void *argv, float *result){
+int xtract_flatness_db(const float *data, const int N, const void *argv, float *result)
+{
 
     float flatness;
 
     flatness = *(float *)argv;
 
-    if (flatness <= 0) 
+    if (flatness <= 0)
         flatness = XTRACT_LOG_LIMIT;
 
     *result = 10 * log10f(flatness);
@@ -523,7 +571,8 @@
 
 }
 
-int xtract_tonality(const float *data, const int N, const void *argv, float *result){
+int xtract_tonality(const float *data, const int N, const void *argv, float *result)
+{
 
     float sfmdb;
 
@@ -534,9 +583,10 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_crest(const float *data, const int N, const void *argv, float *result){
+int xtract_crest(const float *data, const int N, const void *argv, float *result)
+{
 
-    float max, mean; 
+    float max, mean;
 
     max = mean = 0.f;
 
@@ -549,7 +599,8 @@
 
 }
 
-int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
+int xtract_noisiness(const float *data, const int N, const void *argv, float *result)
+{
 
     float h, i, p; /*harmonics, inharmonics, partials */
 
@@ -566,7 +617,8 @@
 
 }
 
-int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
+int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
@@ -579,81 +631,94 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result){
+int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N >> 1;
-    float num = 0.f, den = 0.f, fund; 
+    float num = 0.f, den = 0.f, fund;
     const float *freqs, *amps;
 
     fund = *(float *)argv;
     amps = data;
     freqs = data + n;
 
-    while(n--){
-	if(amps[n]){
-	    num += fabsf(freqs[n] - n * fund) * XTRACT_SQ(amps[n]);
-	    den += XTRACT_SQ(amps[n]);
-	}
+    while(n--)
+    {
+        if(amps[n])
+        {
+            num += fabsf(freqs[n] - n * fund) * XTRACT_SQ(amps[n]);
+            den += XTRACT_SQ(amps[n]);
+        }
     }
 
-    *result = (2 * num) / (fund * den); 
+    *result = (2 * num) / (fund * den);
 
     return XTRACT_SUCCESS;
 }
 
 
-int xtract_power(const float *data, const int N, const void *argv, float *result){
+int xtract_power(const float *data, const int N, const void *argv, float *result)
+{
 
     return XTRACT_FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
+int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result)
+{
 
     int M = (N >> 1), n;
 
     float odd = 0.f, even = 0.f,  temp;
 
-    for(n = 0; n < M; n++){
-	if((temp = data[n])){
-	    if(XTRACT_IS_ODD(n)){
-		odd += temp;
-	    }
-	    else{
-		even += temp;
-	    }
-	}
+    for(n = 0; n < M; n++)
+    {
+        if((temp = data[n]))
+        {
+            if(XTRACT_IS_ODD(n))
+            {
+                odd += temp;
+            }
+            else
+            {
+                even += temp;
+            }
+        }
     }
 
-    if(odd == 0.f || even == 0.f){
+    if(odd == 0.f || even == 0.f)
+    {
         *result = 0.f;
         return XTRACT_NO_RESULT;
     }
-    else {
+    else
+    {
         *result = odd / even;
         return XTRACT_SUCCESS;
     }
 }
 
-int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
+int xtract_sharpness(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, rv;
     float sl, g; /* sl = specific loudness */
-    double temp; 
+    double temp;
 
     sl = g = 0.f;
     temp = 0.f;
 
-    if(n > XTRACT_BARK_BANDS) 
-	rv = XTRACT_BAD_VECTOR_SIZE; 
+    if(n > XTRACT_BARK_BANDS)
+        rv = XTRACT_BAD_VECTOR_SIZE;
     else
-	rv = XTRACT_SUCCESS;
+        rv = XTRACT_SUCCESS;
 
 
-    while(n--){
-	sl = powf(data[n], 0.23);
-	g = (n < 15 ? 1.f : 0.066 * expf(0.171 * n));
-	temp += n * g * sl;
+    while(n--)
+    {
+        sl = powf(data[n], 0.23);
+        g = (n < 15 ? 1.f : 0.066 * expf(0.171 * n));
+        temp += n * g * sl;
     }
 
     temp = 0.11 * temp / (float)N;
@@ -663,97 +728,105 @@
 
 }
 
-int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result){
+int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result)
+{
 
-    const float *freqs, *amps; 
+    const float *freqs, *amps;
     float f, a,
-	  F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
-    int n, M; 
-    
+          F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
+    int n, M;
+
     F = A = FA = FXTRACT_SQ = 0.f;
     n = M = N >> 1;
 
     amps = data;
     freqs = data + n;
 
-    while(n--){
-	f = freqs[n];
-	a = amps[n];
-	F += f;
-	A += a;
-	FA += f * a;
-	FXTRACT_SQ += f * f;
+    while(n--)
+    {
+        f = freqs[n];
+        a = amps[n];
+        F += f;
+        A += a;
+        FA += f * a;
+        FXTRACT_SQ += f * f;
     }
 
-    *result = (1.f / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F); 
+    *result = (1.f / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
 
     return XTRACT_SUCCESS;
 
 }
 
-int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){
+int xtract_lowest_value(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
     float temp;
 
     *result = data[--n];
 
-    while(n--){
-       if((temp = data[n]) > *(float *)argv)	
-	    *result = XTRACT_MIN(*result, data[n]);
+    while(n--)
+    {
+        if((temp = data[n]) > *(float *)argv)
+            *result = XTRACT_MIN(*result, data[n]);
     }
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
+int xtract_highest_value(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     *result = data[--n];
 
-    while(n--) 
-	*result = XTRACT_MAX(*result, data[n]);
+    while(n--)
+        *result = XTRACT_MAX(*result, data[n]);
 
     return XTRACT_SUCCESS;
 }
 
 
-int xtract_sum(const float *data, const int N, const void *argv, float *result){
+int xtract_sum(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
 
     *result = 0.f;
 
     while(n--)
-	*result += *data++;
+        *result += *data++;
 
     return XTRACT_SUCCESS;
 
 }
 
-int xtract_nonzero_count(const float *data, const int N, const void *argv, float *result){
+int xtract_nonzero_count(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N;
-    
+
     *result = 0.f;
 
     while(n--)
-	*result += (*data++ ? 1 : 0);
+        *result += (*data++ ? 1 : 0);
 
     return XTRACT_SUCCESS;
 
 }
 
-int xtract_hps(const float *data, const int N, const void *argv, float *result){
+int xtract_hps(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, M, m, l, peak_index, position1_lwr;
-    float *coeffs2, *coeffs3, *product, L, 
-	  largest1_lwr, peak, ratio1, sr;
+    float *coeffs2, *coeffs3, *product, L,
+          largest1_lwr, peak, ratio1, sr;
 
     sr = *(float*)argv;
     if(sr == 0)
-	sr = 44100.f;
+        sr = 44100.f;
 
     coeffs2 = (float *)malloc(N * sizeof(float));
     coeffs3 = (float *)malloc(N * sizeof(float));
@@ -764,42 +837,48 @@
     M = N >> 1;
     L = N / 3.f;
 
-    while(M--){
-	m = M << 1;
-	coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
+    while(M--)
+    {
+        m = M << 1;
+        coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
 
-	if(M < L){
-	    l = M * 3;
-	    coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3.f;
-	}
+        if(M < L)
+        {
+            l = M * 3;
+            coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3.f;
+        }
     }
 
     peak_index = peak = 0;
 
-    for(n = 1; n < N; n++){
-	product[n] = data[n] * coeffs2[n] * coeffs3[n];
-	if(product[n] > peak){
-	    peak_index = n;
-	    peak = product[n];
-	}
+    for(n = 1; n < N; n++)
+    {
+        product[n] = data[n] * coeffs2[n] * coeffs3[n];
+        if(product[n] > peak)
+        {
+            peak_index = n;
+            peak = product[n];
+        }
     }
 
     largest1_lwr = position1_lwr = 0;
 
-    for(n = 0; n < N; n++){
-	if(data[n] > largest1_lwr && n != peak_index){
-	    largest1_lwr = data[n];
-	    position1_lwr = n;
-	}
+    for(n = 0; n < N; n++)
+    {
+        if(data[n] > largest1_lwr && n != peak_index)
+        {
+            largest1_lwr = data[n];
+            position1_lwr = n;
+        }
     }
 
     ratio1 = data[position1_lwr] / data[peak_index];
 
-    if(position1_lwr > peak_index * 0.4 && position1_lwr < 
-	    peak_index * 0.6 && ratio1 > 0.1)
-	peak_index = position1_lwr;
+    if(position1_lwr > peak_index * 0.4 && position1_lwr <
+            peak_index * 0.6 && ratio1 > 0.1)
+        peak_index = position1_lwr;
 
-    *result = sr / (float)peak_index; 
+    *result = sr / (float)peak_index;
 
     free(coeffs2);
     free(coeffs3);
@@ -809,24 +888,25 @@
 }
 
 
-int xtract_f0(const float *data, const int N, const void *argv, float *result){
+int xtract_f0(const float *data, const int N, const void *argv, float *result)
+{
 
     int M, tau, n;
     float sr;
     size_t bytes;
-    float f0, err_tau_1, err_tau_x, array_max, 
-	  threshold_peak, threshold_centre,
-	  *input;
+    float f0, err_tau_1, err_tau_x, array_max,
+          threshold_peak, threshold_centre,
+          *input;
 
     sr = *(float *)argv;
     if(sr == 0)
-	sr = 44100.f;
+        sr = 44100.f;
 
     input = (float *)malloc(bytes = N * sizeof(float));
     input = memcpy(input, data, bytes);
     /*  threshold_peak = *((float *)argv+1);
-	threshold_centre = *((float *)argv+2);
-	printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
+    threshold_centre = *((float *)argv+2);
+    printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
     /* add temporary dynamic control over thresholds to test clipping effects */
 
     /* FIX: tweak and  make into macros */
@@ -837,75 +917,83 @@
     array_max = 0;
 
     /* Find the array max */
-    for(n = 0; n < N; n++){
-	if (input[n] > array_max)
-	    array_max = input[n];
+    for(n = 0; n < N; n++)
+    {
+        if (input[n] > array_max)
+            array_max = input[n];
     }
 
     threshold_peak *= array_max;
 
     /* peak clip */
-    for(n = 0; n < N; n++){
-	if(input[n] > threshold_peak)
-	    input[n] = threshold_peak;
-	else if(input[n] < -threshold_peak)
-	    input[n] = -threshold_peak;
+    for(n = 0; n < N; n++)
+    {
+        if(input[n] > threshold_peak)
+            input[n] = threshold_peak;
+        else if(input[n] < -threshold_peak)
+            input[n] = -threshold_peak;
     }
 
     threshold_centre *= array_max;
 
     /* Centre clip */
-    for(n = 0; n < N; n++){
-	if (input[n] < threshold_centre)
-	    input[n] = 0;
-	else 
-	    input[n] -= threshold_centre;
+    for(n = 0; n < N; n++)
+    {
+        if (input[n] < threshold_centre)
+            input[n] = 0;
+        else
+            input[n] -= threshold_centre;
     }
 
     /* Estimate fundamental freq */
     for (n = 1; n < M; n++)
-	err_tau_1 = err_tau_1 + fabsf(input[n] - input[n+1]);
-    /* FIX: this doesn't pose too much load if it returns 'early', but if it can't find f0, load can be significant for larger block sizes M^2 iterations! */  
-    for (tau = 2; tau < M; tau++){
-	err_tau_x = 0;
-	for (n = 1; n < M; n++){
-	    err_tau_x = err_tau_x + fabsf(input[n] - input[n+tau]);
-	}
-	if (err_tau_x < err_tau_1) {
-	    f0 = sr / (tau + (err_tau_x / err_tau_1));
-	    *result = f0;
-	    free(input);
-	    return XTRACT_SUCCESS;
-	}
+        err_tau_1 = err_tau_1 + fabsf(input[n] - input[n+1]);
+    /* FIX: this doesn't pose too much load if it returns 'early', but if it can't find f0, load can be significant for larger block sizes M^2 iterations! */
+    for (tau = 2; tau < M; tau++)
+    {
+        err_tau_x = 0;
+        for (n = 1; n < M; n++)
+        {
+            err_tau_x = err_tau_x + fabsf(input[n] - input[n+tau]);
+        }
+        if (err_tau_x < err_tau_1)
+        {
+            f0 = sr / (tau + (err_tau_x / err_tau_1));
+            *result = f0;
+            free(input);
+            return XTRACT_SUCCESS;
+        }
     }
     *result = -0;
     free(input);
     return XTRACT_NO_RESULT;
 }
 
-int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
+int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result)
+{
 
     float *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
 
     return_code = xtract_f0(data, N, argv, result);
 
-    if(return_code == XTRACT_NO_RESULT){
+    if(return_code == XTRACT_NO_RESULT)
+    {
 
-	sr = *(float *)argv;
-	if(sr == 0)
-	    sr = 44100.f;
-	spectrum = (float *)malloc(N * sizeof(float));
-	peaks = (float *)malloc(N * sizeof(float));
-	argf[0] = sr;
-	argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
-	xtract_spectrum(data, N, argf, spectrum);
-	argf[1] = 10.f;
-	xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
-	argf[0] = 0.f;
-	xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
+        sr = *(float *)argv;
+        if(sr == 0)
+            sr = 44100.f;
+        spectrum = (float *)malloc(N * sizeof(float));
+        peaks = (float *)malloc(N * sizeof(float));
+        argf[0] = sr;
+        argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
+        xtract_spectrum(data, N, argf, spectrum);
+        argf[1] = 10.f;
+        xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
+        argf[0] = 0.f;
+        xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
 
-	free(spectrum);
-	free(peaks);
+        free(spectrum);
+        free(peaks);
     }
 
     return XTRACT_SUCCESS;
--- a/src/vector.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/vector.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -25,16 +25,19 @@
 #include <string.h>
 #include <stdlib.h>
 
+#include "fftsg.h"
+
 #include "xtract/libxtract.h"
 #include "xtract_macros_private.h"
 
 #ifndef roundf
-    float roundf(float f){
-        if (f - (int)f >= 0.5) 
-            return (float)((int)f + 1);
-        else
-            return (float)((int)f);
-    }
+float roundf(float f)
+{
+    if (f - (int)f >= 0.5)
+        return (float)((int)f + 1);
+    else
+        return (float)((int)f);
+}
 #endif
 
 #ifndef powf
@@ -53,185 +56,208 @@
 #define fabsf fabs
 #endif
 
-#ifdef XTRACT_FFT
-
-#include <fftw3.h>
 #include "xtract_globals_private.h"
 #include "xtract_macros_private.h"
 
-int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
+int xtract_spectrum(const float *data, const int N, const void *argv, float *result)
+{
 
-    float *input, *rfft, q, temp, max, NxN;
-    size_t bytes;
-    int n,
-        m,
-        M, 
-        vector, 
-        withDC, 
-        argc,
-        normalise;
+    int vector     = 0;
+    int withDC     = 0;
+    int normalise  = 0;
+    float q        = 0.f;
+    float temp     = 0.f;
+    float max      = 0.f;
+    float NxN      = XTRACT_SQ(N);
+    float *marker  = NULL;
+    size_t bytes   = N * sizeof(double);
+    double *rfft    = NULL;
+    unsigned int n = 0;
+    unsigned int m = 0;
+    unsigned int nx2 = 0;
+    unsigned int M = N >> 1;
 
-    vector = argc = withDC = normalise = 0;
+    rfft = (double *)malloc(bytes);
+    //memcpy(rfft, data, bytes);
 
-    M = N >> 1;
-    NxN = XTRACT_SQ(N);
-
-    rfft = (float *)fftwf_malloc(N * sizeof(float));
-    input = (float *)malloc(bytes = N * sizeof(float));
-    input = memcpy(input, data, bytes);
+	for(n = 0; n < N; ++n){
+		rfft[n] = (double)data[n];
+	}
 
     q = *(float *)argv;
     vector = (int)*((float *)argv+1);
     withDC = (int)*((float *)argv+2);
     normalise = (int)*((float *)argv+3);
 
-    temp = 0.f;
-    max = 0.f;
-
     XTRACT_CHECK_q;
 
-    if(fft_plans.spectrum_plan == NULL){
-        fprintf(stderr, 
-                "libxtract: Error: xtract_spectrum() has uninitialised plan\n");
+    if(!ooura_data_spectrum.initialised)
+    {
+        fprintf(stderr,
+                "libxtract: error: xtract_spectrum() failed, "
+                "fft data unitialised.\n");
         return XTRACT_NO_RESULT;
     }
 
-    fftwf_execute_r2r(fft_plans.spectrum_plan, input, rfft);
+    /* ooura is in-place
+     * the output format seems to be
+     * a[0] - DC, a[1] - nyquist, a[2...N-1] - remaining bins
+     */
+    rdft(N, 1, rfft, ooura_data_spectrum.ooura_ip, 
+            ooura_data_spectrum.ooura_w);
 
-    switch(vector){
+    switch(vector)
+    {
 
         case XTRACT_LOG_MAGNITUDE_SPECTRUM:
-            for(n = 0, m = 0; m < M; ++n, ++m){
-                if(!withDC && n == 0){
-                    ++n;
-                }
-                if ((temp = XTRACT_SQ(rfft[n]) + 
-                            XTRACT_SQ(rfft[N - n])) > XTRACT_LOG_LIMIT)
-                    temp = logf(sqrtf(temp) / (float)N);
-                else
-                    temp = XTRACT_LOG_LIMIT_DB;
+        for(n = 0, m = 0; m < M; ++n, ++m)
+        {
+            if(!withDC && n == 0)
+            {
+                continue;
+            }
+            nx2  = n * 2;
+            temp = XTRACT_SQ(rfft[nx2]) + XTRACT_SQ(rfft[nx2+1]);
+            if (temp > XTRACT_LOG_LIMIT)
+            {
+                temp = logf(sqrtf(temp) / (float)N);
+            }
+            else
+            {
+                temp = XTRACT_LOG_LIMIT_DB;
+            }
+            result[m] =
+                /* Scaling */
+                (temp + XTRACT_DB_SCALE_OFFSET) /
+                XTRACT_DB_SCALE_OFFSET;
 
-                result[m] =
-                    /* Scaling */
-                    (temp + XTRACT_DB_SCALE_OFFSET) /
-                    XTRACT_DB_SCALE_OFFSET;
+            XTRACT_SET_FREQUENCY;
+            XTRACT_GET_MAX;
+        }
+        break;
 
-                XTRACT_SET_FREQUENCY;
-                XTRACT_GET_MAX;
+    case XTRACT_POWER_SPECTRUM:
+        for(n = 0, m = 0; m < M; ++n, ++m)
+        {
+            if(!withDC && n == 0)
+            {
+                ++n;
             }
-            break;
+            result[m] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN;
+            XTRACT_SET_FREQUENCY;
+            XTRACT_GET_MAX;
+        }
+        break;
 
-        case XTRACT_POWER_SPECTRUM:
-            for(n = 0, m = 0; m < M; ++n, ++m){
-                if(!withDC && n == 0){
-                    ++n;
-                }
-                result[m] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN;
-                XTRACT_SET_FREQUENCY;
-                XTRACT_GET_MAX;
+    case XTRACT_LOG_POWER_SPECTRUM:
+        for(n = 0, m = 0; m < M; ++n, ++m)
+        {
+            if(!withDC && n == 0)
+            {
+                ++n;
             }
-            break;
+            if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) >
+                    XTRACT_LOG_LIMIT)
+                temp = logf(temp / NxN);
+            else
+                temp = XTRACT_LOG_LIMIT_DB;
 
-        case XTRACT_LOG_POWER_SPECTRUM:
-            for(n = 0, m = 0; m < M; ++n, ++m){
-                if(!withDC && n == 0){
-                    ++n;
-                }
-                if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) >
-                        XTRACT_LOG_LIMIT)
-                    temp = logf(temp / NxN);
-                else
-                    temp = XTRACT_LOG_LIMIT_DB;
+            result[m] = (temp + XTRACT_DB_SCALE_OFFSET) /
+                        XTRACT_DB_SCALE_OFFSET;
+            XTRACT_SET_FREQUENCY;
+            XTRACT_GET_MAX;
+        }
+        break;
 
-                result[m] = (temp + XTRACT_DB_SCALE_OFFSET) /
-                    XTRACT_DB_SCALE_OFFSET; 
-                XTRACT_SET_FREQUENCY;
-                XTRACT_GET_MAX;
+    default:
+        /* MAGNITUDE_SPECTRUM */
+        for(n = 0, m = 0; m < M; ++n, ++m)
+        {
+            marker = &result[m];
+
+            if(n==0 && !withDC) /* discard DC and keep Nyquist */
+            {
+                ++n;
+                marker = &result[M-1];
             }
-            break;
+            if(n==1 && withDC) /* discard Nyquist */
+            {
+                ++n;
+            }
 
-        default:
-            /* MAGNITUDE_SPECTRUM */
-            for(n = 0, m = 0; m < M; ++n, ++m){
-                if(!withDC && n == 0){
-                    ++n;
-                }
-                result[m] = sqrtf(XTRACT_SQ(rfft[n]) + 
-                        XTRACT_SQ(rfft[N - n])) / (float)N;
-                XTRACT_SET_FREQUENCY;
-                XTRACT_GET_MAX;
-            }
-            break;
+            *marker = (float)(sqrt(XTRACT_SQ(rfft[n*2]) +
+                        XTRACT_SQ(rfft[n*2+1])) / (double)N);
 
+            XTRACT_SET_FREQUENCY;
+            XTRACT_GET_MAX;
+
+        }
+        break;
     }
 
-    if(normalise){
+    if(normalise)
+    {
         for(n = 0; n < M; n++)
             result[n] /= max;
     }
 
-    fftwf_free(rfft);
-    free(input);
+    free(rfft);
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
+int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result)
+{
 
-    float *freq, *time;
-    int n, M;
-    //fftwf_plan plan;
+    double *rfft = NULL;
+    int n        = 0;
+    int M        = 0;
 
     M = N << 1;
 
-    freq = (float *)fftwf_malloc(M * sizeof(float));
     /* Zero pad the input vector */
-    time = (float *)calloc(M, sizeof(float));
-    time = memcpy(time, data, N * sizeof(float));
+    rfft = (double *)calloc(M, sizeof(double));
+    memcpy(rfft, data, N * sizeof(float));
 
-    fftwf_execute_r2r(fft_plans.autocorrelation_fft_plan_1, time, freq);
-    //plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE);
+    rdft(M, 1, rfft, ooura_data_autocorrelation_fft.ooura_ip, 
+            ooura_data_autocorrelation_fft.ooura_w);
 
-    //fftwf_execute(plan);
-
-    for(n = 1; n < N; n++){
-        freq[n] = XTRACT_SQ(freq[n]) + XTRACT_SQ(freq[M - n]);
-        freq[M - n] = 0.f;
+    for(n = 2; n < M; n++)
+    {
+        rfft[n*2] = XTRACT_SQ(rfft[n*2]) + XTRACT_SQ(rfft[n*2+1]);
+        rfft[n*2+1] = 0.f;
     }
 
-    freq[0] = XTRACT_SQ(freq[0]);
-    freq[N] = XTRACT_SQ(freq[N]);
+    rfft[0] = XTRACT_SQ(rfft[0]);
+    rfft[1] = XTRACT_SQ(rfft[1]);
 
-    //plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE);
-
-    //fftwf_execute(plan);
-
-    fftwf_execute_r2r(fft_plans.autocorrelation_fft_plan_2, freq, time);
+    rdft(M, -1, rfft, ooura_data_autocorrelation_fft.ooura_ip,
+            ooura_data_autocorrelation_fft.ooura_w);
 
     /* Normalisation factor */
     M = M * N;
 
     for(n = 0; n < N; n++)
-        result[n] = time[n] / (float)M;
-    /* result[n] = time[n+1] / (float)M; */
+        result[n] = rfft[n] / (float)M;
 
-    //fftwf_destroy_plan(plan);
-    fftwf_free(freq);
-    free(time);
+    free(rfft);
 
     return XTRACT_SUCCESS;
 }
 
-int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
+int xtract_mfcc(const float *data, const int N, const void *argv, float *result)
+{
 
     xtract_mel_filter *f;
     int n, filter;
 
     f = (xtract_mel_filter *)argv;
 
-    for(filter = 0; filter < f->n_filters; filter++){
+    for(filter = 0; filter < f->n_filters; filter++)
+    {
         result[filter] = 0.f;
-        for(n = 0; n < N; n++){
+        for(n = 0; n < N; n++)
+        {
             result[filter] += data[n] * f->filters[filter][n];
         }
         result[filter] = logf(result[filter] < XTRACT_LOG_LIMIT ? XTRACT_LOG_LIMIT : result[filter]);
@@ -242,53 +268,25 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_dct(const float *data, const int N, const void *argv, float *result){
+int xtract_dct(const float *data, const int N, const void *argv, float *result)
+{
 
-    //fftwf_plan plan;
+	int n;
+        int m;
+        float *temp = calloc(N, sizeof(float));
 
-    //plan = 
-    //  fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE);
+        for (n = 0; n < N; ++n)
+        {
+            for(m = 1; m <= N; ++m) {
+                temp[n] += data[m - 1] * cos(M_PI * (n / (float)N) * (m - 0.5));
+            }
+        }
 
-    fftwf_execute_r2r(fft_plans.dct_plan, (float *)data, result);
-    //fftwf_execute(plan);
-    //fftwf_destroy_plan(plan);
-
-    return XTRACT_SUCCESS;
+        return XTRACT_SUCCESS;
 }
 
-#else
-
-int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
-
-    XTRACT_NEEDS_FFTW;
-    return XTRACT_NO_RESULT;
-
-}
-
-int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
-
-    XTRACT_NEEDS_FFTW;
-    return XTRACT_NO_RESULT;
-
-}
-
-int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
-
-    XTRACT_NEEDS_FFTW;
-    return XTRACT_NO_RESULT;
-
-}
-
-int xtract_dct(const float *data, const int N, const void *argv, float *result){
-
-    XTRACT_NEEDS_FFTW;
-    return XTRACT_NO_RESULT;
-
-}
-
-#endif
-
-int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){
+int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result)
+{
 
     /* Naive time domain implementation  */
 
@@ -296,9 +294,11 @@
 
     float corr;
 
-    while(n--){
+    while(n--)
+    {
         corr = 0;
-        for(i = 0; i < N - n; i++){
+        for(i = 0; i < N - n; i++)
+        {
             corr += data[i] * data[i + n];
         }
         result[n] = corr / N;
@@ -307,15 +307,18 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_amdf(const float *data, const int N, const void *argv, float *result){
+int xtract_amdf(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, i;
 
     float md, temp;
 
-    while(n--){
+    while(n--)
+    {
         md = 0.f;
-        for(i = 0; i < N - n; i++){
+        for(i = 0; i < N - n; i++)
+        {
             temp = data[i] - data[i + n];
             temp = (temp < 0 ? -temp : temp);
             md += temp;
@@ -326,15 +329,18 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_asdf(const float *data, const int N, const void *argv, float *result){
+int xtract_asdf(const float *data, const int N, const void *argv, float *result)
+{
 
     int n = N, i;
 
     float sd;
 
-    while(n--){
+    while(n--)
+    {
         sd = 0.f;
-        for(i = 0; i < N - n; i++){
+        for(i = 0; i < N - n; i++)
+        {
             /*sd = 1;*/
             sd += XTRACT_SQ(data[i] - data[i + n]);
         }
@@ -344,13 +350,15 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
+int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result)
+{
 
     int *limits, band, n;
 
     limits = (int *)argv;
 
-    for(band = 0; band < XTRACT_BARK_BANDS - 1; band++){
+    for(band = 0; band < XTRACT_BARK_BANDS - 1; band++)
+    {
         result[band] = 0.f;
         for(n = limits[band]; n < limits[band + 1]; n++)
             result[band] += data[n];
@@ -359,7 +367,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){
+int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result)
+{
 
     float threshold, max, y, y2, y3, p, q, *input = NULL;
     size_t bytes;
@@ -367,14 +376,16 @@
 
     threshold = max = y = y2 = y3 = p = q = 0.f;
 
-    if(argv != NULL){
+    if(argv != NULL)
+    {
         q = ((float *)argv)[0];
         threshold = ((float *)argv)[1];
     }
     else
         rv = XTRACT_BAD_ARGV;
 
-    if(threshold < 0 || threshold > 100){
+    if(threshold < 0 || threshold > 100)
+    {
         threshold = 0;
         rv = XTRACT_BAD_ARGV;
     }
@@ -398,32 +409,38 @@
     result[0] = 0;
     result[N] = 0;
 
-    for(n = 1; n < N; n++){
-        if(input[n] >= threshold){
-            if(input[n] > input[n - 1] && n + 1 < N && input[n] > input[n + 1]){
-                result[N + n] = q * (n + (p = .5 * ((y = input[n-1]) - 
-                                (y3 = input[n+1])) / (input[n - 1] - 2 * 
-                                    (y2 = input[n]) + input[n + 1])));
+    for(n = 1; n < N; n++)
+    {
+        if(input[n] >= threshold)
+        {
+            if(input[n] > input[n - 1] && n + 1 < N && input[n] > input[n + 1])
+            {
+                result[N + n] = q * (n + (p = .5 * ((y = input[n-1]) -
+                                                    (y3 = input[n+1])) / (input[n - 1] - 2 *
+                                                            (y2 = input[n]) + input[n + 1])));
                 result[n] = y2 - .25 * (y - y3) * p;
             }
-            else{
+            else
+            {
                 result[n] = 0;
                 result[N + n] = 0;
             }
         }
-        else{
+        else
+        {
             result[n] = 0;
             result[N + n] = 0;
         }
-    }	  
+    }
 
     free(input);
     return (rv ? rv : XTRACT_SUCCESS);
 }
 
-int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){
+int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result)
+{
 
-    int n = (N >> 1), M = n; 
+    int n = (N >> 1), M = n;
 
     const float *freqs, *amps;
     float f0, threshold, ratio, nearest, distance;
@@ -435,14 +452,17 @@
 
     ratio = nearest = distance = 0.f;
 
-    while(n--){
-        if(freqs[n]){
+    while(n--)
+    {
+        if(freqs[n])
+        {
             ratio = freqs[n] / f0;
             nearest = roundf(ratio);
             distance = fabs(nearest - ratio);
             if(distance > threshold)
                 result[n] = result[M + n] = 0.f;
-            else {
+            else
+            {
                 result[n] = amps[n];
                 result[M + n] = freqs[n];
             }
@@ -453,14 +473,15 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_lpc(const float *data, const int N, const void *argv, float *result){
+int xtract_lpc(const float *data, const int N, const void *argv, float *result)
+{
 
     int i, j, k, M, L;
-    float r = 0.f, 
+    float r = 0.f,
           error = 0.f;
 
     float *ref = NULL,
-          *lpc = NULL ;
+           *lpc = NULL ;
 
     error = data[0];
     k = N; /* The length of *data */
@@ -469,24 +490,27 @@
     ref = result;
     lpc = result+L;
 
-    if(error == 0.0){
+    if(error == 0.0)
+    {
         memset(result, 0, M * sizeof(float));
         return XTRACT_NO_RESULT;
     }
 
     memset(result, 0, M * sizeof(float));
 
-    for (i = 0; i < L; i++) {
+    for (i = 0; i < L; i++)
+    {
 
         /* Sum up this iteration's reflection coefficient. */
         r = -data[i + 1];
-        for (j = 0; j < i; j++) 
+        for (j = 0; j < i; j++)
             r -= lpc[j] * data[i - j];
         ref[i] = r /= error;
 
         /* Update LPC coefficients and total error. */
         lpc[i] = r;
-        for (j = 0; j < i / 2; j++) {
+        for (j = 0; j < i / 2; j++)
+        {
             float tmp      = lpc[j];
             lpc[j]          = r * lpc[i - 1 - j];
             lpc[i - 1 - j] += r * tmp;
@@ -499,7 +523,8 @@
     return XTRACT_SUCCESS;
 }
 
-int xtract_lpcc(const float *data, const int N, const void *argv, float *result){
+int xtract_lpcc(const float *data, const int N, const void *argv, float *result)
+{
 
     /* Given N lpc coefficients extract an LPC cepstrum of size argv[0] */
     /* Based on an an algorithm by rabiner and Juang */
@@ -507,7 +532,7 @@
     int n, k;
     float sum;
     int order = N - 1; /* Eventually change this to Q = 3/2 p as suggested in Rabiner */
-    int cep_length; 
+    int cep_length;
 
     if(argv == NULL)
         cep_length = N - 1; /* FIX: if we're going to have default values, they should come from the descriptor */
@@ -517,7 +542,8 @@
 
     memset(result, 0, cep_length * sizeof(float));
 
-    for (n = 1; n <= order && n <= cep_length; n++){
+    for (n = 1; n <= order && n <= cep_length; n++)
+    {
         sum = 0.f;
         for (k = 1; k < n; k++)
             sum += k * result[k-1] * data[n - k];
@@ -525,7 +551,8 @@
     }
 
     /* be wary of these interpolated values */
-    for(n = order + 1; n <= cep_length; n++){
+    for(n = order + 1; n <= cep_length; n++)
+    {
         sum = 0.f;
         for (k = n - (order - 1); k < n; k++)
             sum += k * result[k-1] * data[n - k];
@@ -539,7 +566,8 @@
 //    return XTRACT_SUCCESS;
 //}
 
-int xtract_subbands(const float *data, const int N, const void *argv, float *result){
+int xtract_subbands(const float *data, const int N, const void *argv, float *result)
+{
 
     int n, bw, xtract_func, nbands, scale, start, lower, *argi, rv;
 
@@ -558,10 +586,12 @@
     lower = start;
     rv = XTRACT_SUCCESS;
 
-    for(n = 0; n < nbands; n++){
+    for(n = 0; n < nbands; n++)
+    {
 
         /* Bounds sanity check */
-        if(lower >= N || lower + bw >= N){
+        if(lower >= N || lower + bw >= N)
+        {
             //   printf("n: %d\n", n);
             result[n] = 0.f;
             continue;
@@ -572,14 +602,15 @@
         if(rv != XTRACT_SUCCESS)
             return rv;
 
-        switch(scale){
-            case XTRACT_OCTAVE_SUBBANDS:
-                lower += bw;
-                bw = lower;
-                break;
-            case XTRACT_LINEAR_SUBBANDS:
-                lower += bw;
-                break;
+        switch(scale)
+        {
+        case XTRACT_OCTAVE_SUBBANDS:
+            lower += bw;
+            bw = lower;
+            break;
+        case XTRACT_LINEAR_SUBBANDS:
+            lower += bw;
+            break;
         }
 
     }
--- a/src/window.c	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/window.c	Mon Jan 07 16:27:15 2013 +0000
@@ -1,5 +1,5 @@
 /* libxtract feature extraction library
- *  
+ *
  * Copyright (C) 2006 Jamie Bullock
  *
  * This program is free software; you can redistribute it and/or modify
@@ -14,7 +14,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
  * USA.
  */
 
@@ -24,7 +24,8 @@
 
 #include "xtract_window_private.h"
 
-void gauss(float *window, const int N, const float sd){
+void gauss(float *window, const int N, const float sd)
+{
 
     int n;
     const float M = N - 1;
@@ -32,11 +33,12 @@
           den,
           exponent;
 
-    for (n = 0; n < N; n++) {
+    for (n = 0; n < N; n++)
+    {
 
         num = n - M / 2.f;
         den = sd * M / 2.f;
-        
+
         exponent = -0.5 * powf(num / den, 2);
 
         window[n] = exp(exponent);
@@ -44,7 +46,8 @@
     }
 }
 
-void hamming(float *window, const int N){
+void hamming(float *window, const int N)
+{
 
     int n;
     const float M = N - 1;
@@ -54,7 +57,8 @@
 
 }
 
-void hann(float *window, const int N){
+void hann(float *window, const int N)
+{
 
     int n;
     const float M = N - 1;
@@ -64,7 +68,8 @@
 
 }
 
-void bartlett(float *window, const int N){
+void bartlett(float *window, const int N)
+{
 
     int n;
     const float M = N - 1;
@@ -74,7 +79,8 @@
 
 }
 
-void triangular(float *window, const int N){
+void triangular(float *window, const int N)
+{
 
     int n;
     const float M = N - 1;
@@ -83,17 +89,19 @@
         window[n] = 2.f / N * (N / 2.f - fabsf(n - M / 2.f));
 }
 
-void bartlett_hann(float *window, const int N){
+void bartlett_hann(float *window, const int N)
+{
 
     int n;
     const float M = N - 1,
-          a0 = 0.62,
-          a1 = 0.5,
-          a2 = 0.38;
+                a0 = 0.62,
+                a1 = 0.5,
+                a2 = 0.38;
     float term1 = 0.f,
           term2 = 0.f;
 
-    for (n = 0; n < N; n++){
+    for (n = 0; n < N; n++)
+    {
 
         term1 = a1 * fabsf(n / M - 0.5);
         term2 = a2 * cosf(2.0 * PI * (float)n / M);
@@ -102,18 +110,20 @@
     }
 }
 
-void blackman(float *window, const int N){
+void blackman(float *window, const int N)
+{
 
     int n;
     const float M = N - 1,
-          a0 = 0.42,
-          a1 = 0.5,
-          a2 = 0.08;
+                a0 = 0.42,
+                a1 = 0.5,
+                a2 = 0.08;
     float term1 = 0.f,
           term2 = 0.f;
 
-    for (n = 0; n < N; n++) {
-    
+    for (n = 0; n < N; n++)
+    {
+
         term1 = a1 * cosf(2.0 * PI * (float)n / M);
         term2 = a2 * cosf(4.0 * PI * (float)n / M);
 
@@ -124,54 +134,61 @@
 #define BIZ_EPSILON 1E-21 // Max error acceptable 
 
 /* Based on code from mplayer window.c, and somewhat beyond me */
-float besselI0(float x){
+float besselI0(float x)
+{
 
-  float temp;
-  float sum   = 1.0;
-  float u     = 1.0;
-  float halfx = x/2.0;
-  int      n     = 1;
+    float temp;
+    float sum   = 1.0;
+    float u     = 1.0;
+    float halfx = x/2.0;
+    int      n     = 1;
 
-  do {
+    do
+    {
 
-    temp = halfx/(float)n;
-    u *=temp * temp;
-    sum += u;
-    n++;
+        temp = halfx/(float)n;
+        u *=temp * temp;
+        sum += u;
+        n++;
 
-  } while (u >= BIZ_EPSILON * sum);
+    }
+    while (u >= BIZ_EPSILON * sum);
 
-  return(sum);
+    return(sum);
 
 }
 
-void kaiser(float *window, const int N, const float alpha){
+void kaiser(float *window, const int N, const float alpha)
+{
 
     int n;
     const float M = N - 1;
     float num;
 
-    for (n = 0; n < N; n++) {
+    for (n = 0; n < N; n++)
+    {
 
         num = besselI0(alpha * sqrtf(1.0 - powf((2.0 * n / M - 1), 2)));
         window[n] = num / besselI0(alpha);
-        
+
     }
 }
 
-void blackman_harris(float *window, const int N){
+void blackman_harris(float *window, const int N)
+{
 
     int n;
     const float M = N - 1,
-          a0 = 0.35875,
-          a1 = 0.48829,
-          a2 = 0.14128,
-          a3 = 0.01168;
+                a0 = 0.35875,
+                a1 = 0.48829,
+                a2 = 0.14128,
+                a3 = 0.01168;
     float term1 = 0.f,
           term2 = 0.f,
           term3 = 0.f;
 
-    for (n = 0; n < N; n++) {
+    for (n = 0; n < N; n++)
+    {
 
         term1 = a1 * cosf(2.0 * PI * n / M);
         term2 = a2 * cosf(4.0 * PI * n / M);
--- a/src/xtract_globals_private.h	Thu Sep 13 10:56:43 2012 +0100
+++ b/src/xtract_globals_private.h	Mon Jan 07 16:27:15 2013 +0000
@@ -23,17 +23,12 @@
 #ifndef XTRACT_GLOBALS_PRIVATE_H
 #define XTRACT_GLOBALS_PRIVATE_H
 
-#ifdef XTRACT_FFT
-#include <fftw3.h>
-
-struct xtract_fft_plans_ {
-    
-    fftwf_plan spectrum_plan;
-    fftwf_plan autocorrelation_fft_plan_1;
-    fftwf_plan autocorrelation_fft_plan_2;
-    fftwf_plan dct_plan;
-
-};
+typedef struct xtract_ooura_data_
+{
+    int *ooura_ip;
+    double *ooura_w;
+    bool initialised;
+} xtract_ooura_data;
 
 #ifdef DEFINE_GLOBALS
 #define GLOBAL
@@ -41,9 +36,10 @@
 #define GLOBAL extern
 #endif
 
-GLOBAL struct xtract_fft_plans_ fft_plans;
-
-#endif /* FFT */
+GLOBAL struct xtract_ooura_data_ ooura_data_dct;
+GLOBAL struct xtract_ooura_data_ ooura_data_mfcc;
+GLOBAL struct xtract_ooura_data_ ooura_data_spectrum;
+GLOBAL struct xtract_ooura_data_ ooura_data_autocorrelation_fft;
 
 #endif /* Header guard */
 
--- a/swig/java/Makefile.am	Thu Sep 13 10:56:43 2012 +0100
+++ b/swig/java/Makefile.am	Mon Jan 07 16:27:15 2013 +0000
@@ -1,3 +1,4 @@
+MAINTAINERCLEANFILES = all-local $(javasources) Makefile.in
 
 javasources = \
 	SWIGTYPE_p_float.java \
@@ -61,8 +62,6 @@
 	xtract_vector_t.class \
 	xtract_window_types_.class 
 
-MAINTAINERCLEANFILES = $(javasources) Makefile.in
-
 BUILT_SOURCES = $(srcdir)/xtract_wrap.c
 SWIG_SOURCES = jxtract.i
 
--- a/swig/java/SWIG.java	Thu Sep 13 10:56:43 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,16 +0,0 @@
-package xtract.core;
-
-public abstract class SWIG {
-  protected abstract long getPointer();
-
-  public boolean equals(Object obj) {
-    boolean equal = false;
-    if (obj instanceof SWIG)
-      equal = (((SWIG)obj).getPointer() == this.getPointer());
-    return equal;
-  }
-  
-  public SWIGTYPE_p_void getVoidPointer() {
-    return new SWIGTYPE_p_void(getPointer(), false);
-  }
-}
--- a/xtract/xtract_helper.h	Thu Sep 13 10:56:43 2012 +0100
+++ b/xtract/xtract_helper.h	Mon Jan 07 16:27:15 2013 +0000
@@ -27,6 +27,8 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
+
 /**
   * \defgroup helper helper functions
   *
@@ -66,6 +68,9 @@
 /** \brief Test whether a number is denormal */
 int xtract_is_denormal(double const d);
 
+/** \brief Test whether a number is a power of two */
+bool xtract_is_poweroftwo(unsigned int x);
+
 /** @} */
 
 #ifdef __cplusplus