aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog11
-rw-r--r--TODO1
-rw-r--r--configure.in23
-rw-r--r--examples/MSP/xtract~.c27
-rw-r--r--examples/puredata/simple-example.pd30
-rw-r--r--examples/puredata/xtract/f0.pd30
-rw-r--r--examples/puredata/xtract/xtract-help.pd53
-rw-r--r--examples/puredata/xtract~.c36
-rw-r--r--src/Makefile.am2
-rw-r--r--src/init.c84
-rw-r--r--src/vector.c60
-rw-r--r--src/xtract_macros_private.h5
-rw-r--r--xtract/libxtract.h13
-rw-r--r--xtract/xtract_delta.h2
-rw-r--r--xtract/xtract_vector.h2
15 files changed, 286 insertions, 93 deletions
diff --git a/ChangeLog b/ChangeLog
index b8d74f1..c9bb0af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2007-10-06 Jamie Bullock <jamie@postlude.co.uk>
+ * version 0.5.0
+ * Removed fftw_plan creation from inner loop of functions that use fft
+ * Added new init function xtract_init_fft() for initialisation of
+ fft_plan out-of-place. The actual plans have global scope, and are
+ freed by the library destructor.
+ * Updated Max/MSP and PD examples too reflect the above change
+ * Made the fft optimistation level a compile-time option through
+ --with-fft-optimisation flag (0 = lowest, 2 = highest).
+ * Minor fixes.
+
2007-10-04 Dan Stowell
* version 0.4.9
* Fixed and tidied MFCC functions
diff --git a/TODO b/TODO
index b167e1f..62d8070 100644
--- a/TODO
+++ b/TODO
@@ -12,3 +12,4 @@ Add Max/MSP external example
Check and add return values as appropriate. Make them more sensible!
...do other stuff and eventually...
...optimise!
+Use the fftw guru interface to create multipurpose global plans from xtract_fft_init()
diff --git a/configure.in b/configure.in
index 8027fd5..bf3703a 100644
--- a/configure.in
+++ b/configure.in
@@ -2,9 +2,9 @@ AC_PREREQ(2.13)
# 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, 4)
+m4_define(libxtract_minor_version, 5)
# Increment for fixes
-m4_define(libxtract_fix_version, 9)
+m4_define(libxtract_fix_version, 0)
m4_define(libxtract_version, libxtract_major_version.libxtract_minor_version.libxtract_fix_version)
@@ -85,6 +85,16 @@ AC_ARG_WITH(fftw3_dir,
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) ],
@@ -140,7 +150,7 @@ AC_ARG_ENABLE(debug,
if test "$with_debug" = "yes"
then
AC_DEFINE(DEBUG,1,[Define to enable debug])
- CFLAGS="$CFLAGS -O0 -ggdb -g"
+ CFLAGS="$CFLAGS -O0 -ggdb -g -Werror"
fi
AC_ARG_ENABLE(swig,
@@ -188,6 +198,13 @@ 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
diff --git a/examples/MSP/xtract~.c b/examples/MSP/xtract~.c
index 11a40f5..69b7f69 100644
--- a/examples/MSP/xtract~.c
+++ b/examples/MSP/xtract~.c
@@ -40,6 +40,9 @@ typedef struct _xtract {
void *outlet; /*Float outlet */
t_float f;
t_int feature;
+ t_symbol *feature_name;
+ t_int init_blocksize;
+ t_int done_init;
t_int feature_type;
tracked_memory memory;
void *argv;
@@ -75,6 +78,11 @@ static t_int *xtract_perform_vector(t_int *w) {
if(x->feature == XTRACT_PEAK_SPECTRUM)
N >>= 1;
+ if(N != x->init_blocksize && x->done_init){
+ post("xtract~ %s: Blocksize mismatch, try specifying the blocksize as a second argument", x->feature_name->s_name);
+ return (w+5);
+ }
+
n = N;
temp_in = (float *)getbytes(N * sizeof(float));
@@ -114,14 +122,12 @@ static void *xtract_tilde_new(t_symbol *me, t_int argc, t_atom *argv) {
t_symbol *tmp;
t_xtract_tilde *x = (t_xtract_tilde *)newobject(xtract_tilde_class);
xtract_mel_filter *mf;
- t_int n, N, f, F, n_args, type, blocksize;
+ t_int n, N, f, F, n_args, type;
t_float *argv_max;
xtract_function_descriptor_t *fd;
char *p_name, *p_desc, *author;
int year;
-
- blocksize = BLOCKSIZE; /* Default */
tmp = NULL;
p_name = p_desc = author = NULL;
@@ -129,16 +135,17 @@ static void *xtract_tilde_new(t_symbol *me, t_int argc, t_atom *argv) {
f = F = XTRACT_FEATURES;
- /* N = BLOCKSIZE;*/
+ N = BLOCKSIZE;
x->argv = NULL;
+ x->done_init = 0;
if(argc)
tmp = argv[0].a_w.w_sym; /*atom_getsymbol(argv); */
if(argc > 1)
- blocksize = (t_int)argv[1].a_w.w_long;
+ N = (t_int)argv[1].a_w.w_long;
- N = blocksize;
+ x->init_blocksize = N;
/* get function descriptors */
fd = (xtract_function_descriptor_t *)xtract_make_descriptors();
@@ -214,6 +221,14 @@ static void *xtract_tilde_new(t_symbol *me, t_int argc, t_atom *argv) {
else if(x->feature == XTRACT_BARK_COEFFICIENTS)
xtract_init_bark(N, NYQUIST, x->argv);
+ /* Initialise fft_plan if required */
+ if(x->feature == XTRACT_AUTOCORRELATION_FFT ||
+ x->feature == XTRACT_SPECTRUM ||
+ x->feature == XTRACT_DCT){
+ xtract_init_fft(N, x->feature);
+ x->done_init = 1;
+ }
+
if(x->feature == XTRACT_AUTOCORRELATION ||
x->feature == XTRACT_AUTOCORRELATION_FFT ||
x->feature == XTRACT_MFCC || x->feature == XTRACT_AMDF ||
diff --git a/examples/puredata/simple-example.pd b/examples/puredata/simple-example.pd
index 510fb2f..80e8761 100644
--- a/examples/puredata/simple-example.pd
+++ b/examples/puredata/simple-example.pd
@@ -1,8 +1,26 @@
-#N canvas 0 0 450 300 10;
+#N canvas 5 48 450 300 10;
+#X obj 154 42 osc~ 440;
+#X floatatom 154 180 8 0 0 0 - - -;
+#N canvas 619 86 450 300 spectral_mean 1;
#X obj 144 80 xtract~ spectrum;
-#X obj 154 26 osc~ 440;
-#X obj 145 129 xtract~ spectral_mean;
-#X floatatom 146 184 5 0 0 0 - - -;
+#X obj 346 21 block~ 1024;
+#X obj 145 47 inlet~;
+#X obj 145 190 outlet;
+#X obj 145 129 xtract~ spectral_centroid;
+#X msg 269 57 list \$1;
+#X msg 270 11 44100;
+#X obj 270 33 / 1024;
+#X obj 67 130 print~;
+#X obj 73 104 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144 -1
+-1;
+#X connect 0 0 4 0;
+#X connect 0 0 8 0;
+#X connect 2 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 0 1;
+#X connect 6 0 7 0;
+#X connect 7 0 5 0;
+#X connect 9 0 8 0;
+#X restore 154 115 pd spectral_mean;
#X connect 0 0 2 0;
-#X connect 1 0 0 0;
-#X connect 2 0 3 0;
+#X connect 2 0 1 0;
diff --git a/examples/puredata/xtract/f0.pd b/examples/puredata/xtract/f0.pd
index 47dc649..6ea0714 100644
--- a/examples/puredata/xtract/f0.pd
+++ b/examples/puredata/xtract/f0.pd
@@ -53,7 +53,7 @@
#X connect 4 0 3 0;
#X connect 4 0 1 1;
#X restore 587 66 pd noise;
-#N canvas 135 136 496 580 pda 0;
+#N canvas 554 114 496 580 pda 0;
#X obj 99 100 xtract~ f0;
#X obj 197 6 inlet~;
#X msg 361 203 list \$1;
@@ -79,7 +79,6 @@
#X msg 60 48 list \$1;
#X obj 274 59 r \$0-window-gen;
#X obj 274 80 a_hann 2048;
-#X obj 147 195 xtract~ spectrum;
#X obj 148 222 xtract~ peak_spectrum;
#X obj 149 315 xtract~ lowest_value;
#X obj 150 243 a_blockswap~ 2048;
@@ -87,15 +86,16 @@
#X obj 358 150 / 2048;
#X msg 358 171 \$1 10;
#X obj 356 105 r \$0-peak-args;
+#X obj 147 195 xtract~ spectrum 2048;
#X connect 0 0 2 0;
#X connect 0 0 8 0;
#X connect 0 0 9 0;
#X connect 0 0 11 0;
#X connect 1 0 19 0;
-#X connect 2 0 27 1;
-#X connect 3 0 25 0;
+#X connect 2 0 26 1;
+#X connect 3 0 32 0;
#X connect 4 0 22 0;
-#X connect 7 0 27 0;
+#X connect 7 0 26 0;
#X connect 8 0 9 1;
#X connect 9 0 12 0;
#X connect 10 0 12 0;
@@ -112,14 +112,14 @@
#X connect 22 0 0 1;
#X connect 23 0 24 0;
#X connect 24 0 3 1;
-#X connect 25 0 26 0;
-#X connect 26 0 28 0;
-#X connect 27 0 10 0;
-#X connect 28 0 5 0;
+#X connect 25 0 27 0;
+#X connect 26 0 10 0;
+#X connect 27 0 5 0;
+#X connect 28 0 29 0;
#X connect 29 0 30 0;
-#X connect 30 0 31 0;
-#X connect 31 0 26 1;
-#X connect 32 0 29 0;
+#X connect 30 0 25 1;
+#X connect 31 0 28 0;
+#X connect 32 0 25 0;
#X restore 357 262 pd pda;
#N canvas 0 0 596 417 d_saw 0;
#X obj 382 176 phasor~;
@@ -250,14 +250,14 @@
#X obj 11 -226 cnv 15 500 200 empty empty PDA_comparison 20 12 0 14
-261681 -66577 0;
#X obj 34 -94 hsl 128 15 2 2.05 0 0 \$0-inharmonicity empty fm-inharmonicity
--2 -6 0 8 -225271 -1 -1 800 1;
+-2 -6 0 8 -225271 -1 -1 0 1;
#X obj 34 -50 hsl 128 15 0 0.5 0 0 \$0-noisiness empty noisiness -2
-6 0 8 -225271 -1 -1 0 1;
#X obj 33 -135 hsl 128 15 30 3000 0 0 \$0-fund empty f0 -2 -6 0 8 -225271
--1 -1 300 1;
+-1 -1 0 1;
#X obj 32 -172 tgl 15 0 \$0-sine empty sine 0 -6 0 8 -225280 -1 -1
0 1;
-#X obj 73 -172 tgl 15 0 \$0-fm empty fm 0 -6 0 8 -225280 -1 -1 1 1
+#X obj 73 -172 tgl 15 0 \$0-fm empty fm 0 -6 0 8 -225280 -1 -1 0 1
;
#X obj 110 -172 tgl 15 0 \$0-saw empty saw 0 -6 0 8 -225280 -1 -1 0
1;
diff --git a/examples/puredata/xtract/xtract-help.pd b/examples/puredata/xtract/xtract-help.pd
index 6a7435b..8e0959b 100644
--- a/examples/puredata/xtract/xtract-help.pd
+++ b/examples/puredata/xtract/xtract-help.pd
@@ -6,34 +6,37 @@ library: LibXtract. Please refer to the documentation at libxtract.sourceforge.n
\, for a full explanation of the library and the functions it provides.
Only the operation of the PD external will be explained here along
with a few use case scenarios.;
-#X text 20 148 [xtract~] must always be called with one argument \,
-in the following form: [xtract~ <feature>] \, where <feature> is a
-feature supported by the LibXtract library. A complete list of features
-may be obtained by sending the external a |help( message:;
-#X obj 27 262 xtract~;
-#X msg 27 233 help;
-#X text 26 298 Other than this help message \, the data sent to the
+#X obj 27 299 xtract~;
+#X msg 27 270 help;
+#X text 27 328 Other than this help message \, the data sent to the
left inlet should always be a 'signal' (i.e. audio rate). This is the
data from a which a given feature will be extracted.;
-#X obj 182 490 xtract~ mean;
-#X floatatom 132 586 10 0 0 0 - - -;
-#X floatatom 253 523 5 0 0 0 - - -;
-#X msg 182 522 list \$1;
-#X obj 132 556 xtract~ variance;
-#X obj 181 466 phasor~ 0.1;
-#X text 39 641 Below are some possible use cases (click to open):;
-#X text 26 352 The outlet may be a scalar (control rate) \, or a vector
+#X obj 183 520 xtract~ mean;
+#X floatatom 133 616 10 0 0 0 - - -;
+#X floatatom 254 553 5 0 0 0 - - -;
+#X msg 183 552 list \$1;
+#X obj 133 586 xtract~ variance;
+#X obj 182 496 phasor~ 0.1;
+#X text 40 671 Below are some possible use cases (click to open):;
+#X text 27 382 The outlet may be a scalar (control rate) \, or a vector
(audio rate) \, depending on the nature of the feature that is being
extracted.;
-#X obj 42 665 f0;
-#X obj 83 665 mfcc;
-#X text 27 405 Any additional arguments that need to be passed to the
+#X obj 43 695 f0;
+#X obj 84 695 mfcc;
+#X text 28 435 Any additional arguments that need to be passed to the
feature extraction function must be provided as a list to the right
inlet \, e.g.;
-#X connect 5 0 4 0;
-#X connect 7 0 9 0;
-#X connect 7 0 10 0;
-#X connect 10 0 11 1;
-#X connect 11 0 8 0;
-#X connect 12 0 7 0;
-#X connect 12 0 11 0;
+#X text 24 231 A complete list of features may be obtained by sending
+the external a |help( message:;
+#X text 20 148 [xtract~] must always be called with one argument \,
+in the following form: [xtract~ <feature>] \, where <feature> is a
+feature supported by the LibXtract library.;
+#X text 21 198 An optional second argument can be used to explicitly
+set the blocksize for FFT-based features;
+#X connect 4 0 3 0;
+#X connect 6 0 8 0;
+#X connect 6 0 9 0;
+#X connect 9 0 10 1;
+#X connect 10 0 7 0;
+#X connect 11 0 6 0;
+#X connect 11 0 10 0;
diff --git a/examples/puredata/xtract~.c b/examples/puredata/xtract~.c
index 3f07cd3..e58aea0 100644
--- a/examples/puredata/xtract~.c
+++ b/examples/puredata/xtract~.c
@@ -48,6 +48,9 @@ typedef struct _xtract {
t_float f;
t_int feature;
t_int feature_type;
+ t_symbol *feature_name;
+ t_int init_blocksize;
+ t_int done_init;
tracked_memory memory;
void *argv;
} t_xtract_tilde;
@@ -72,6 +75,7 @@ static t_int *xtract_perform(t_int *w) {
}
static t_int *xtract_perform_vector(t_int *w) {
+
t_sample *in = (t_sample *)(w[1]);
t_sample *out = (t_sample *)(w[2]);
t_float *tmp_in, *tmp_out;
@@ -79,6 +83,11 @@ static t_int *xtract_perform_vector(t_int *w) {
t_int N = (t_int)(w[4]), n;
t_int return_code = 0;
+ if(N != x->init_blocksize && x->done_init){
+ error("xtract~ %s: Blocksize mismatch, try specifying the blocksize as a second argument", x->feature_name->s_name);
+ return (w+5);
+ }
+
n = N;
tmp_in = copybytes(in, N * sizeof(t_float));
@@ -112,7 +121,6 @@ static void xtract_dsp(t_xtract_tilde *x, t_signal **sp) {
static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
- t_symbol *tmp;
t_xtract_tilde *x = (t_xtract_tilde *)pd_new(xtract_class);
xtract_mel_filter *mf;
t_int n, N, f, F, n_args, type;
@@ -130,8 +138,14 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
N = BLOCKSIZE;
x->argv = NULL;
+ x->done_init = 0;
- tmp = atom_getsymbol(argv);
+ if(argc)
+ x->feature_name = atom_getsymbol(argv);
+ if(argc > 1)
+ N = atom_getint(&argv[1]);
+
+ x->init_blocksize = N;
/* get function descriptors */
fd = (xtract_function_descriptor_t *)xtract_make_descriptors();
@@ -139,7 +153,7 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
/* iterate over descriptors */
while(f--){
/* map creation arg to feature */
- if(tmp == gensym(fd[f].algo.name)){
+ if(x->feature_name == gensym(fd[f].algo.name)){
x->feature = f;
break;
}
@@ -170,7 +184,6 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
x->memory.argv = 0;
}
-
p_name = fd[f].algo.p_name;
p_desc = fd[f].algo.p_desc;
author = fd[f].algo.author;
@@ -203,10 +216,21 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
mf->filters[n] = (float *)getbytes(N * sizeof(float));
xtract_init_mfcc(N, NYQUIST, XTRACT_EQUAL_GAIN, 80.0f,
- 18000.0f, mf->n_filters, mf->filters);
+ 18000.0f, mf->n_filters, mf->filters);
+ x->done_init = 1;
}
- else if(x->feature == XTRACT_BARK_COEFFICIENTS)
+ else if(x->feature == XTRACT_BARK_COEFFICIENTS){
xtract_init_bark(N, NYQUIST, x->argv);
+ x->done_init = 1;
+ }
+
+ /* Initialise fft_plan if required */
+ if(x->feature == XTRACT_AUTOCORRELATION_FFT ||
+ x->feature == XTRACT_SPECTRUM ||
+ x->feature == XTRACT_DCT){
+ xtract_init_fft(N, x->feature);
+ x->done_init = 1;
+ }
if(x->feature == XTRACT_AUTOCORRELATION ||
x->feature == XTRACT_AUTOCORRELATION_FFT ||
diff --git a/src/Makefile.am b/src/Makefile.am
index 8dc7691..bee5c4d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
-SOURCES = libxtract.c descriptors.c scalar.c vector.c delta.c init.c
+SOURCES = libxtract.c descriptors.c scalar.c vector.c delta.c init.c fini.c
if BUILD_FFT
FFT_DEFINE = -DXTRACT_FFT
diff --git a/src/init.c b/src/init.c
index 35802d0..a0e0b03 100644
--- a/src/init.c
+++ b/src/init.c
@@ -20,10 +20,24 @@
/* init.c: defines functions that extract a feature as a single value from an input vector */
-#include "xtract/libxtract.h"
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include <math.h>
#include <stdlib.h>
+#include "xtract/libxtract.h"
+#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 n, i, k, *fft_peak, M, next_peak;
@@ -113,6 +127,10 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
fft_tables[n][k] = 0.f;
}
+
+ /* Initialise the fft_plan for the DCT */
+ xtract_init_fft(freq_bands, XTRACT_MFCC);
+
free(mel_peak);
free(lin_peak);
free(height_norm);
@@ -122,6 +140,69 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
}
+int xtract_init_fft(int N, int feature_name){
+
+ float *input, *output;
+ int optimisation;
+
+ input = output = NULL;
+
+ fprintf(stderr, "Optimisation level: %d\n", XTRACT_FFT_OPTIMISATION_LEVEL);
+
+ 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(feature_name == XTRACT_AUTOCORRELATION_FFT)
+ N <<= 1;
+
+ input = malloc(N * sizeof(float));
+ output = malloc(N * sizeof(float));
+
+ switch(feature_name){
+ case XTRACT_SPECTRUM:
+ if(spectrum_plan != NULL)
+ fftwf_destroy_plan(spectrum_plan);
+ spectrum_plan =
+ fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
+ break;
+ case XTRACT_AUTOCORRELATION_FFT:
+ if(autocorrelation_fft_plan_1 != NULL)
+ fftwf_destroy_plan(autocorrelation_fft_plan_1);
+ if(autocorrelation_fft_plan_2 != NULL)
+ fftwf_destroy_plan(autocorrelation_fft_plan_2);
+ autocorrelation_fft_plan_1 =
+ fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
+ autocorrelation_fft_plan_2 =
+ fftwf_plan_r2r_1d(N, input, output, FFTW_HC2R, optimisation);
+ break;
+ case XTRACT_DCT:
+ if(dct_plan != NULL)
+ fftwf_destroy_plan(dct_plan);
+ dct_plan =
+ fftwf_plan_r2r_1d(N, input, output, FFTW_REDFT00, optimisation);
+ case XTRACT_MFCC:
+ if(dct_plan != NULL)
+ fftwf_destroy_plan(dct_plan);
+ dct_plan =
+ fftwf_plan_r2r_1d(N, output, output, FFTW_REDFT00, optimisation);
+ break;
+ }
+
+ free(input);
+ free(output);
+
+ return XTRACT_SUCCESS;
+
+}
+
+#endif
+
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)*/
@@ -134,3 +215,4 @@ int xtract_init_bark(int N, float sr, int *band_limits){
return XTRACT_SUCCESS;
}
+
diff --git a/src/vector.c b/src/vector.c
index 19596ff..a9c5290 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -21,12 +21,13 @@
/* xtract_vector.c: defines functions that extract a feature as a single value from an input vector */
-#include "xtract/libxtract.h"
-#include "xtract_macros_private.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
+#include "xtract/libxtract.h"
+#include "xtract_macros_private.h"
+
#ifndef roundf
float roundf(float f){
if (f - (int)f >= 0.5)
@@ -39,17 +40,20 @@
#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){
float *input, *rfft, q, temp;
size_t bytes;
- int n , NxN, M, vector, withDC;
- fftwf_plan plan;
+ int n , NxN, M, vector, withDC, argc;
+ //fftwf_plan plan;
+
+ vector = argc = withDC = 0;
M = N >> 1;
NxN = XTRACT_SQ(N);
- withDC = 0;
rfft = (float *)fftwf_malloc(N * sizeof(float));
input = (float *)malloc(bytes = N * sizeof(float));
@@ -61,9 +65,16 @@ int xtract_spectrum(const float *data, const int N, const void *argv, float *res
XTRACT_CHECK_q;
- plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE);
-
- fftwf_execute(plan);
+ if(spectrum_plan == NULL){
+ /* FIX: Not sure this should really be here. Might introduce
+ * DEBUG_POST macro, or some kind of error handler, or leave it to the
+ * caller... */
+ fprintf(stderr,
+ "libxtract: Error: xtract_spectrum() has uninitialised plan\n");
+ return XTRACT_NO_RESULT;
+ }
+
+ fftwf_execute_r2r(spectrum_plan, input, rfft);
switch(vector){
@@ -152,11 +163,10 @@ int xtract_spectrum(const float *data, const int N, const void *argv, float *res
}
else {
/* The Nyquist */
- result[M - 1] = XTRACT_SQ(rfft[M]);
+ result[M - 1] = (float)XTRACT_SQ(rfft[M]);
result[N - 1] = q * M;
}
- fftwf_destroy_plan(plan);
fftwf_free(rfft);
free(input);
@@ -167,7 +177,7 @@ int xtract_autocorrelation_fft(const float *data, const int N, const void *argv,
float *freq, *time;
int n, M;
- fftwf_plan plan;
+ //fftwf_plan plan;
M = N << 1;
@@ -176,9 +186,10 @@ int xtract_autocorrelation_fft(const float *data, const int N, const void *argv,
time = (float *)calloc(M, sizeof(float));
time = memcpy(time, data, N * sizeof(float));
- plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE);
+ fftwf_execute_r2r(autocorrelation_fft_plan_1, time, freq);
+ //plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE);
- fftwf_execute(plan);
+ //fftwf_execute(plan);
for(n = 1; n < N; n++){
freq[n] = XTRACT_SQ(freq[n]) + XTRACT_SQ(freq[M - n]);
@@ -188,9 +199,11 @@ int xtract_autocorrelation_fft(const float *data, const int N, const void *argv,
freq[0] = XTRACT_SQ(freq[0]);
freq[N] = XTRACT_SQ(freq[N]);
- plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE);
+ //plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE);
- fftwf_execute(plan);
+ //fftwf_execute(plan);
+
+ fftwf_execute_r2r(autocorrelation_fft_plan_2, freq, time);
/* Normalisation factor */
M = M * N;
@@ -199,7 +212,7 @@ int xtract_autocorrelation_fft(const float *data, const int N, const void *argv,
result[n] = time[n] / (float)M;
/* result[n] = time[n+1] / (float)M; */
- fftwf_destroy_plan(plan);
+ //fftwf_destroy_plan(plan);
fftwf_free(freq);
free(time);
@@ -228,13 +241,14 @@ int xtract_mfcc(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;
+ //fftwf_plan plan;
- plan =
- fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE);
+ //plan =
+ // fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE);
- fftwf_execute(plan);
- fftwf_destroy_plan(plan);
+ fftwf_execute_r2r(dct_plan, (float *)data, result);
+ //fftwf_execute(plan);
+ //fftwf_destroy_plan(plan);
return XTRACT_SUCCESS;
}
@@ -363,7 +377,9 @@ int xtract_peak_spectrum(const float *data, const int N, const void *argv, float
XTRACT_CHECK_q;
- input = (float *)malloc(bytes = N * sizeof(float));
+ input = (float *)calloc(N, sizeof(float));
+
+ bytes = N * sizeof(float);
if(input != NULL)
input = memcpy(input, data, bytes);
diff --git a/src/xtract_macros_private.h b/src/xtract_macros_private.h
index 7f06960..bfe0b63 100644
--- a/src/xtract_macros_private.h
+++ b/src/xtract_macros_private.h
@@ -49,9 +49,6 @@
(= SR_LOWER_LIMIT / FFT_BANDS_MAX*/
#define XTRACT_SPEC_BW_MAX 12000.0 /* SR_UPPER_LIMIT / FFT_BANDS_MIN */
#define XTRACT_SPEC_BW_DEF 43.066 /* SR_DEFAULT / FFT_BANDS_DEF */
-
-#ifdef __cplusplus
-}
-#endif
+#define XTRACT_ARRAY_ELEMENTS(_array) (sizeof(_array)/sizeof(_array[0]))
#endif
diff --git a/xtract/libxtract.h b/xtract/libxtract.h
index af69758..e967372 100644
--- a/xtract/libxtract.h
+++ b/xtract/libxtract.h
@@ -261,7 +261,7 @@ typedef struct _xtract_function_descriptor {
*
* \param N: the number of elements to be processed
*
- * \param *argv: an abitrary number of additional arguments, used to pass additional parameters to the function being called
+ * \param *argv: an abitrary number of additional arguments, used to pass additional parameters to the function being called. All arguments are compulsary!
*
* \param *result: a pointer to the first element in the result
*
@@ -326,6 +326,17 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
*/
int xtract_init_bark(int N, float sr, int *band_limits);
+/** \brief An initialisation function for functions using FFT
+ *
+ * This function initialises global data structures used by functions requiring FFT functionality. It can be called multiple times with different feature names. Calling it more than once with the same feature name is not a valid operation and will result in a memory leak.
+ *
+ * \param N: the size of the FFT
+ * \param feature_name: the name of the feature the FFT is being used for,
+ * e.g. XTRACT_DCT
+ *
+ */
+int xtract_init_fft(int N, int feature_name);
+
/* \brief A function to build an array of function descriptors */
void *xtract_make_descriptors();
diff --git a/xtract/xtract_delta.h b/xtract/xtract_delta.h
index 9c6910a..706c812 100644
--- a/xtract/xtract_delta.h
+++ b/xtract/xtract_delta.h
@@ -47,8 +47,6 @@ int xtract_delta_feature(const float *data, const int N, const void *argv, float
/*xtract_frame_tracker *xf */
/*float frames*/
-
-
#ifdef __cplusplus
}
#endif
diff --git a/xtract/xtract_vector.h b/xtract/xtract_vector.h
index ad97f16..e67ae6d 100644
--- a/xtract/xtract_vector.h
+++ b/xtract/xtract_vector.h
@@ -38,7 +38,7 @@ extern "C" {
*
* \param *data: a pointer to the first element in an array of floats representing an audio vector
* \param N: the number of array elements to be considered
- * \param *argv: a pointer to an array of floats, the first representing (samplerate / N), the second will be cast to an integer and determines the spectrum type (e.g. XTRACT_MAGNITUDE_SPECTRUM, XTRACT_LOG_POWER_SPECTRUM). An optional third argument determines whether or not the DC component is included in the output. If argv[2] == 1, then the DC component is included in which case the size of the array pointed to by *result must be N+2. For any further use of the array pointed to by *result, the value of N must reflect the (larger) array size.
+ * \param *argv: a pointer to an array of floats, the first representing (samplerate / N), the second will be cast to an integer and determines the spectrum type (e.g. XTRACT_MAGNITUDE_SPECTRUM, XTRACT_LOG_POWER_SPECTRUM). The third argument determines whether or not the DC component is included in the output. If argv[2] == 1, then the DC component is included in which case the size of the array pointed to by *result must be N+2. For any further use of the array pointed to by *result, the value of N must reflect the (larger) array size.
* \param *result: a pointer to an array of size N containing N/2 magnitude/power/log magnitude/log power coefficients and N/2 bin frequencies.
*/
int xtract_spectrum(const float *data, const int N, const void *argv, float *result);