changeset 43:4a36f70a76e9

Numerous fixes and enhancements, see ChangeLog.
author Jamie Bullock <jamie@postlude.co.uk>
date Fri, 15 Dec 2006 21:17:12 +0000
parents 84e69b155098
children b2e7e24c9a9c
files ChangeLog configure.in examples/puredata/xtract~.c src/delta.c src/init.c src/libxtract.c src/scalar.c src/vector.c xtract/libxtract.h xtract/xtract_delta.h xtract/xtract_scalar.h xtract/xtract_vector.h
diffstat 12 files changed, 291 insertions(+), 161 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Tue Dec 12 21:47:42 2006 +0000
+++ b/ChangeLog	Fri Dec 15 21:17:12 2006 +0000
@@ -1,3 +1,17 @@
+2006-12-15 Jamie Bullock <jamie@postlude.co.uk>
+    * version 0.3.4
+	* Changed xtract_lowest_match(), to xtract_lowest(). It just returns the
+	lowest non-zero component in the input array, between two bounds
+	* qualified int *data, int N, and void *argv as const, thus insuring
+	that they won't be modified by the called function.
+	* added facilities for some functions to operate on copies of input
+	data instead of modifying it. This will need to be optimised at some
+	point maybe.
+	* Added arguments to spectral flatness to allow for control over input
+	band and pre-scaling
+	* Fixed confusing xtract_init_mfcc() parameter order
+	* Added new xtractor xtract_failsafe_f0
+
 2006-12-12 Jamie Bullock <jamie@postlude.co.uk>
     * version 0.3.3
 	* Fixed errors in skewnes, kurtosis, irregularity_k, irregularity_j,
--- a/configure.in	Tue Dec 12 21:47:42 2006 +0000
+++ b/configure.in	Fri Dec 15 21:17:12 2006 +0000
@@ -4,7 +4,7 @@
 # Increment for feature additions and enhancements
 m4_define(libxtract_minor_version, 3)
 # Increment for fixes 
-m4_define(libxtract_fix_version, 2)
+m4_define(libxtract_fix_version, 4)
 
 m4_define(libxtract_version, libxtract_major_version.libxtract_minor_version.libxtract_fix_version)
 		
--- a/examples/puredata/xtract~.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/examples/puredata/xtract~.c	Fri Dec 15 21:17:12 2006 +0000
@@ -141,7 +141,7 @@
     else if(tmp == gensym("slope")) x->feature = SLOPE;
     else if(tmp == gensym("f0")) x->feature = F0;
     else if(tmp == gensym("hps"))x->feature = HPS;
-    else if(tmp == gensym("lowest_match"))x->feature = LOWEST_MATCH;
+    else if(tmp == gensym("lowest"))x->feature = LOWEST;
     else if(tmp == gensym("dct")) x->feature = DCT;
     else if(tmp == gensym("magnitude_spectrum")) 
                                         x->feature = MAGNITUDE_SPECTRUM;
@@ -168,7 +168,7 @@
 	case  AVERAGE_DEVIATION:
 	case  ROLLOFF:
 	case  INHARMONICITY:
-	case  LOWEST_MATCH:
+	case  ODD_EVEN_RATIO:
 	case  F0:
 	case  TONALITY:
 	    floatargs = 1;
@@ -176,6 +176,7 @@
 	case  SKEWNESS:
 	case  KURTOSIS:
 	case  PEAKS:
+	case  LOWEST:
 	case  HARMONICS:
 	    floatargs = 2;
 	    break;
@@ -194,7 +195,6 @@
 	case  NOISINESS:
 	case  RMS_AMPLITUDE:
 	case  POWER:
-	case  ODD_EVEN_RATIO:
 	case  SHARPNESS:
 	case  SLOPE:
 	case  HPS:
--- a/src/delta.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/src/delta.c	Fri Dec 15 21:17:12 2006 +0000
@@ -22,25 +22,25 @@
 
 #include "xtract/libxtract.h"
 
-int xtract_flux(float *data, int N, void *argv , float *result){
+int xtract_flux(const float *data, const int N, const void *argv , float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_attack_time(float *data, int N, void *argv , float *result){
+int xtract_attack_time(const float *data, const int N, const void *argv , float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_decay_time(float *data, int N, void *argv, float *result){
+int xtract_decay_time(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_delta_feature(float *data, int N, void *argv, float *result){
+int xtract_delta_feature(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
--- a/src/init.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/src/init.c	Fri Dec 15 21:17:12 2006 +0000
@@ -24,7 +24,7 @@
 #include <math.h>
 #include <stdlib.h>
 
-int xtract_init_mfcc(int N, float nyquist, int style, float freq_max, float freq_min, 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, 
--- a/src/libxtract.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/src/libxtract.c	Fri Dec 15 21:17:12 2006 +0000
@@ -22,7 +22,7 @@
 #include "xtract/libxtract.h"
 #define XTRACT
 
-int(*xtract[])(float *, int, void *, float *) = {
+int(*xtract[])(const float *, const int, const void *, float *) = {
     /* xtract_scalar.h */
     xtract_mean,
     xtract_variance,
@@ -51,9 +51,10 @@
     xtract_odd_even_ratio,
     xtract_sharpness,
     xtract_slope,
-    xtract_lowest_match,
+    xtract_lowest,
     xtract_hps,
     xtract_f0,
+    xtract_failsafe_f0,
 /* xtract_delta.h */
     xtract_flux,
     xtract_attack_time,
@@ -100,9 +101,10 @@
    "xtract_odd_even_ratio",
    "xtract_sharpness",
    "xtract_slope",
-   "xtract_lowest_match",
+   "xtract_lowest",
    "xtract_hps",
    "xtract_f0",
+   "xtract_failsafe_f0",
    "xtract_flux",
    "xtract_attack_time",
    "xtract_decay_time",
--- a/src/scalar.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/src/scalar.c	Fri Dec 15 21:17:12 2006 +0000
@@ -24,8 +24,9 @@
 #include "xtract/libxtract.h"
 #include "math.h"
 #include <stdlib.h>
+#include <string.h>
 
-int xtract_mean(float *data, int N, void *argv, float *result){
+int xtract_mean(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -37,26 +38,26 @@
     return SUCCESS;
 }
 
-int xtract_variance(float *data, int N, void *argv, float *result){
+int xtract_variance(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
     while(n--)
-	*result += data[n] - *(float *)argv;
+	*result += pow(data[n] - *(float *)argv, 2);
 
-    *result = SQ(*result) / (N - 1);
+    *result = *result / (N - 1);
     
     return SUCCESS;
 }
 
-int xtract_standard_deviation(float *data, int N, void *argv, float *result){
+int xtract_standard_deviation(const float *data, const int N, const void *argv, float *result){
 
     *result = sqrt(*(float *)argv);
 
     return SUCCESS;
 }
 
-int xtract_average_deviation(float *data, int N, void *argv, float *result){
+int xtract_average_deviation(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
     
@@ -68,7 +69,7 @@
     return SUCCESS;
 }
 
-int xtract_skewness(float *data, int N, void *argv,  float *result){
+int xtract_skewness(const float *data, const int N, const void *argv,  float *result){
 
     int n = N;
 
@@ -84,7 +85,7 @@
     return SUCCESS;
 }
 
-int xtract_kurtosis(float *data, int N, void *argv,  float *result){
+int xtract_kurtosis(const float *data, const int N, const void *argv,  float *result){
 
     int n = N;
 
@@ -102,11 +103,12 @@
 }
 
 
-int xtract_centroid(float *data, int N, void *argv,  float *result){
+int xtract_centroid(const float *data, const int N, const void *argv,  float *result){
 
     int n = (N >> 1);
 
-    float *freqs, *amps, FA = 0.f, A = 0.f;
+    const float *freqs, *amps;
+    float FA = 0.f, A = 0.f;
 
     freqs = data;
     amps = data + n;
@@ -121,7 +123,7 @@
     return SUCCESS;
 }
 
-int xtract_irregularity_k(float *data, int N, void *argv, float *result){
+int xtract_irregularity_k(const float *data, const int N, const void *argv, float *result){
 
     int n,
 	M = N - 1;
@@ -132,7 +134,7 @@
     return SUCCESS;
 }
 
-int xtract_irregularity_j(float *data, int N, void *argv, float *result){
+int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -148,7 +150,7 @@
     return SUCCESS;
 }
 
-int xtract_tristimulus_1(float *data, int N, void *argv, float *result){
+int xtract_tristimulus_1(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -169,7 +171,7 @@
     return SUCCESS;
 }
 
-int xtract_tristimulus_2(float *data, int N, void *argv, float *result){
+int xtract_tristimulus_2(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -194,7 +196,7 @@
     return SUCCESS;
 }
 
-int xtract_tristimulus_3(float *data, int N, void *argv, float *result){
+int xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result){
 
     int n = N, count = 0;
 
@@ -216,23 +218,30 @@
     return SUCCESS;
 }
 
-int xtract_smoothness(float *data, int N, void *argv, float *result){
+int xtract_smoothness(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
-    if (data[0] <= 0) data[0] = 1;
-    if (data[1] <= 0) data[1] = 1;
+    float *input;
+
+    input = (float *)malloc(N * sizeof(float));
+    input = memcpy(input, data, N * sizeof(float));
+
+    if (input[0] <= 0) input[0] = 1;
+    if (input[1] <= 0) input[1] = 1;
 
     for(n = 2; n < N; n++){ 
-	if(data[n] <= 0) data[n] = 1;
-	*result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) + 
-		    20 * log(data[n-1]) + 20 * log(data[n])) / 3);
+	if(input[n] <= 0) input[n] = 1;
+	*result += abs(20 * log(input[n-1]) - (20 * log(input[n-2]) + 
+		    20 * log(input[n-1]) + 20 * log(input[n])) / 3);
     }
+
+    free(input);
     
     return SUCCESS;
 }
 
-int xtract_spread(float *data, int N, void *argv, float *result){
+int xtract_spread(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -249,7 +258,7 @@
     return SUCCESS;
 }
 
-int xtract_zcr(float *data, int N, void *argv, float *result){
+int xtract_zcr(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -261,7 +270,7 @@
     return SUCCESS;
 }
 
-int xtract_rolloff(float *data, int N, void *argv, float *result){
+int xtract_rolloff(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
     float pivot, temp;
@@ -280,7 +289,7 @@
     return SUCCESS;
 }
 
-int xtract_loudness(float *data, int N, void *argv, float *result){
+int xtract_loudness(const float *data, const int N, const void *argv, float *result){
 
     int n = BARK_BANDS;
 
@@ -293,16 +302,25 @@
 }
 
 
-int xtract_flatness(float *data, int N, void *argv, float *result){
+int xtract_flatness(const float *data, const int N, const void *argv, float *result){
 
     int n;
 
-    float num, den, temp;
+    float num, den, temp, *tmp, prescale; 
+    int lower, upper; 
 
+    tmp = (float *)argv;
+    lower = (int)tmp[0];
+    upper = (int)tmp[1];
+    prescale = (float)tmp[2]; 
+
+    upper = (upper > N ? N : upper);
+    lower = (lower < 0.f ? 0.f : lower);
+    
     den = temp = num = 0.f;
 
-    for(n = 0; n < N; n++){
-	if((temp = data[n])){
+    for(n = lower; n < upper; n++){
+	if((temp = data[n] * prescale)){
 	    if(!num)
 		num = den = temp;
 	    else{
@@ -320,7 +338,7 @@
     return SUCCESS;
 }
 
-int xtract_tonality(float *data, int N, void *argv, float *result){
+int xtract_tonality(const float *data, const int N, const void *argv, float *result){
 
     float sfmdb, sfm;
 
@@ -333,19 +351,19 @@
     return SUCCESS;
 }
 
-int xtract_crest(float *data, int N, void *argv, float *result){
+int xtract_crest(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_noisiness(float *data, int N, void *argv, float *result){
+int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_rms_amplitude(float *data, int N, void *argv, float *result){
+int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
 
     int n = N;
 
@@ -356,11 +374,11 @@
     return SUCCESS;
 }
 
-int xtract_inharmonicity(float *data, int N, void *argv, float *result){
+int xtract_inharmonicity(const float *data, const int N, const void *argv, float *result){
 
     int n = N >> 1;
-    float num = 0.f, den = 0.f,
-	  fund, *freqs, *amps;
+    float num = 0.f, den = 0.f, fund; 
+    const float *freqs, *amps;
 
     fund = *(float *)argv;
     freqs = data;
@@ -377,23 +395,29 @@
 }
 
 
-int xtract_power(float *data, int N, void *argv, float *result){
+int xtract_power(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){
+int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
 
-    int n = N, j, k;
+    int M = (N >> 1), n;
 
-    float num = 0.f, den = 0.f;
+    float num = 0.f, den = 0.f,  temp, f0;
 
-    while(n--){
-	j = n * 2;
-	k = j - 1;
-	num += data[k];
-	den += data[j];
+    f0 = *(float *)argv;
+    
+    for(n = 0; n < M; n++){
+	if((temp = data[n])){
+	    if(((int)(rintf(temp / f0)) % 2) != 0){
+		num += data[M + n];
+	    }
+	    else{
+		den += data[M + n];
+	    }
+	}
     }
 
     *result = num / den;
@@ -401,34 +425,39 @@
     return SUCCESS;
 }
 
-int xtract_sharpness(float *data, int N, void *argv, float *result){
+int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_slope(float *data, int N, void *argv, float *result){
+int xtract_slope(const float *data, const int N, const void *argv, float *result){
 
     return FEATURE_NOT_IMPLEMENTED;
 
 }
 
-int xtract_lowest_match(float *data, int N, void *argv, float *result){
+int xtract_lowest(const float *data, const int N, const void *argv, float *result){
 
-    float lowest_match = SR_LIMIT;
+    float lower, upper, lowest;
     int n = N;
 
+    lower = *(float *)argv;
+    upper = *((float *)argv+1);
+    
+    lowest = upper;
+
     while(n--) {
-	if(data[n] > 0)
-	    lowest_match = MIN(lowest_match, data[n]);
+	if(data[n] > lower)
+	    *result = MIN(lowest, data[n]);
     }
 
-    *result = (lowest_match == SR_LIMIT ? 0 : lowest_match);
-
+    *result = (*result == upper ? -0 : *result);
+    
     return SUCCESS;
 }
 
-int xtract_hps(float *data, int N, 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, 
@@ -490,12 +519,18 @@
 }
 
 
-int xtract_f0(float *data, int N, void *argv, float *result){
+int xtract_f0(const float *data, const int N, const void *argv, float *result){
 
     int M, sr, tau, n;
-    float f0, err_tau_1, err_tau_x, array_max, threshold_peak, threshold_centre;
+    size_t bytes;
+    float f0, err_tau_1, err_tau_x, array_max, 
+	  threshold_peak, threshold_centre,
+	  *input;
 
     sr = *(float *)argv;
+
+    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);*/
@@ -510,44 +545,74 @@
 
     /* Find the array max */
     for(n = 0; n < N; n++){
-	if (data[n] > array_max)
-	    array_max = data[n];
+	if (input[n] > array_max)
+	    array_max = input[n];
     }
 
     threshold_peak *= array_max;
 
     /* peak clip */
     for(n = 0; n < N; n++){
-	if(data[n] > threshold_peak)
-	    data[n] = threshold_peak;
-	else if(data[n] < -threshold_peak)
-	    data[n] = -threshold_peak;
+	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 (data[n] < threshold_centre)
-	    data[n] = 0;
+	if (input[n] < threshold_centre)
+	    input[n] = 0;
 	else 
-	    data[n] -= threshold_centre;
+	    input[n] -= threshold_centre;
     }
 
     /* Estimate fundamental freq */
     for (n = 1; n < M; n++)
-	err_tau_1 = err_tau_1 + fabs(data[n] - data[n+1]);
+	err_tau_1 = err_tau_1 + fabs(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 + fabs(data[n] - data[n+tau]);
+	    err_tau_x = err_tau_x + fabs(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 SUCCESS;
 	}
     }
+    *result = -0;
+    free(input);
     return NO_RESULT;
 }
+
+int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
+    
+    float *magnitudes = NULL, argf[2], *peaks = NULL, return_code;
+    
+    return_code = xtract_f0(data, N, argv, result);
+    
+    if(return_code == NO_RESULT){
+	
+	magnitudes = (float *)malloc(N * sizeof(float));
+	peaks = (float *)malloc(N * sizeof(float));
+	xtract_magnitude_spectrum(data, N, NULL, magnitudes);
+	argf[0] = 10.f;
+	argf[1] = *(float *)argv;
+	xtract_peaks(magnitudes, N, argf, peaks);
+	argf[0] = 0.f;
+	argf[1] = N >> 1;
+	xtract_lowest(peaks, argf[1], argf, result);
+	
+	free(magnitudes);
+	free(peaks);
+    }
+
+    return SUCCESS;
+
+}
+	
--- a/src/vector.c	Tue Dec 12 21:47:42 2006 +0000
+++ b/src/vector.c	Fri Dec 15 21:17:12 2006 +0000
@@ -23,20 +23,25 @@
 
 #include "xtract/libxtract.h"
 #include <math.h>
+#include <string.h>
+#include <stdlib.h>
 
 #ifdef XTRACT_FFT
 
 #include <fftw3.h>
 
-int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
+int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result){
 
-    float *temp;
+    float *temp, *input;
+    size_t bytes;
     int n , M = N >> 1;
     fftwf_plan plan;
 
     temp = (float *)fftwf_malloc(N * sizeof(float));
+    input = (float *)malloc(bytes = N * sizeof(float));
+    input = memcpy(input, data, bytes);
 
-    plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_R2HC, FFTW_ESTIMATE);
+    plan = fftwf_plan_r2r_1d(N, input, temp, FFTW_R2HC, FFTW_ESTIMATE);
     
     fftwf_execute(plan);
     
@@ -50,18 +55,23 @@
     
     fftwf_destroy_plan(plan);
     fftwf_free(temp);
+    free(input);
     
     return SUCCESS;
 }
 
-int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
+int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
     
-    float *temp;
+    float *temp, *input;
+    size_t bytes;
     int n;
     fftwf_plan plan;
 
     temp = (float *)fftwf_malloc(N * sizeof(float));
-    plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_HC2R, FFTW_ESTIMATE);
+    input = (float *)malloc(bytes = N * sizeof(float));
+    input = memcpy(input, data, bytes);
+
+    plan = fftwf_plan_r2r_1d(N, input, temp, FFTW_HC2R, FFTW_ESTIMATE);
 
     fftwf_execute(plan);
     
@@ -70,20 +80,26 @@
     
     fftwf_destroy_plan(plan);
     fftwf_free(temp);
+    free(input);
 
     return SUCCESS;
 }
 
-int xtract_mfcc(float *data, int N, void *argv, float *result){
+int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
 
     xtract_mel_filter *f;
+    float *input;
+    size_t bytes;
     int n, filter;
 
     f = (xtract_mel_filter *)argv;
     
+    input = (float *)malloc(bytes = N * sizeof(float));
+    input = memcpy(input, data, bytes);
+    
     for(filter = 0; filter < f->n_filters; filter++){
         for(n = 0; n < N; n++){
-            result[filter] += data[n] * f->filters[filter][n];
+            result[filter] += input[n] * f->filters[filter][n];
         }
         if(result[filter] < LOG_LIMIT) result[filter] = LOG_LIMIT;
         result[filter] = log(result[filter]);
@@ -93,43 +109,51 @@
     
     xtract_dct(result, f->n_filters, NULL, result);
 
+    free(input);
+    
     return SUCCESS;
 }
 
-int xtract_dct(float *data, int N, void *argv, float *result){
+int xtract_dct(const float *data, const int N, const void *argv, float *result){
     
     fftwf_plan plan;
+    float *input;
+    size_t bytes;
 
+    input = (float *)malloc(bytes = N * sizeof(float));
+    input = memcpy(input, data, bytes);
+    
     plan = 
-        fftwf_plan_r2r_1d(N, data, result, FFTW_REDFT00, FFTW_ESTIMATE);
+        fftwf_plan_r2r_1d(N, input, result, FFTW_REDFT00, FFTW_ESTIMATE);
     
     fftwf_execute(plan);
     fftwf_destroy_plan(plan);
+    free(input);
 
     return SUCCESS;
 }
 
 #else
 
-int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
+int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result){
 
     NEEDS_FFTW;
 
 }
 
-int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
+int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
 
     NEEDS_FFTW;
 
 }
 
-int xtract_mfcc(float *data, int N, void *argv, float *result){
+int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
 
     NEEDS_FFTW;
 
 }
 
-int xtract_dct(float *data, int N, void *argv, float *result){
+int xtract_dct(const float *data, const int N, const void *argv, float *result){
 
     NEEDS_FFTW;
 
@@ -137,7 +161,7 @@
 
 #endif
 
-int xtract_autocorrelation(float *data, int N, void *argv, float *result){
+int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){
 
     /* Naive time domain implementation  */
     
@@ -156,7 +180,7 @@
     return SUCCESS;
 }
 
-int xtract_amdf(float *data, int N, void *argv, float *result){
+int xtract_amdf(const float *data, const int N, const void *argv, float *result){
 
     int n = N, i;
     
@@ -175,7 +199,7 @@
     return SUCCESS;
 }
 
-int xtract_asdf(float *data, int N, void *argv, float *result){
+int xtract_asdf(const float *data, const int N, const void *argv, float *result){
     
     int n = N, i;
     
@@ -193,7 +217,7 @@
     return SUCCESS;
 }
 
-int xtract_bark_coefficients(float *data, int N, void *argv, float *result){
+int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
 
     int *limits, band, n;
 
@@ -207,9 +231,12 @@
     return SUCCESS;
 }
 
-int xtract_peaks(float *data, int N, void *argv, float *result){
+int xtract_peaks(const float *data, const int N, const void *argv, float *result){
 
-    float thresh, max, y, y2, y3, p, width, sr; 
+    float thresh, max, y, y2, 
+	  y3, p, width, sr,
+	  *input = NULL;
+    size_t bytes;
     int n = N, M, return_code = SUCCESS;
     
     if(argv != NULL){
@@ -222,6 +249,13 @@
         sr = 44100;
     }
 
+    input = (float *)malloc(bytes = N * sizeof(float));
+
+    if(input != NULL)
+	input = memcpy(input, data, bytes);
+    else
+	return MALLOC_FAILED;
+
     M = N >> 1;
     width = sr / N;
     
@@ -238,12 +272,12 @@
     }
 
     while(n--){
-        max = MAX(max, data[n]);
+        max = MAX(max, input[n]);
         /* ensure we never take log10(0) */
-        /*data[n] = (data[n] < LOG_LIMIT ? LOG_LIMIT : data[n]);*/
-        if ((data[n] * 100000) <= 1)
+        /*input[n] = (input[n] < LOG_LIMIT ? LOG_LIMIT : input[n]);*/
+        if ((input[n] * 100000) <= 1)
         /* We get a more stable peak this way */
-		    data[n] = 1;
+		    input[n] = 1;
         
     }
     
@@ -253,9 +287,9 @@
     result[M] = 0;
 
     for(n = 1; n < M; n++){
-        if(data[n] >= thresh){
-            if(data[n] > data[n - 1] && data[n] > data[n + 1]){
-                result[n] = width * (n + (p = .5 * (y = 20 * log10(data[n-1]) - (y3 = 20 * log10(data[n+1]))) / (20 * log10(data[n - 1]) - 2 * (y2 = 20 * log10(data[n])) + 20 * log10(data[n + 1]))));
+        if(input[n] >= thresh){
+            if(input[n] > input[n - 1] && input[n] > input[n + 1]){
+                result[n] = width * (n + (p = .5 * (y = 20 * log10(input[n-1]) - (y3 = 20 * log10(input[n+1]))) / (20 * log10(input[n - 1]) - 2 * (y2 = 20 * log10(input[n])) + 20 * log10(input[n + 1]))));
                 result[M + n] = y2 - .25 * (y - y3) * p;
             }
             else{
@@ -269,14 +303,16 @@
         }
     }	  
    
+    free(input);
     return (return_code ? return_code : SUCCESS);
 }
 	    
-int xtract_harmonics(float *data, int N, void *argv, float *result){
+int xtract_harmonics(const float *data, const int N, const void *argv, float *result){
     
     int n = (N >> 1), M = n; 
 
-    float *freqs, *amps, f0, thresh, ratio, nearest, distance;
+    const float *freqs, *amps;
+    float f0, thresh, ratio, nearest, distance;
 
     freqs = data;
     amps = data + n;
--- a/xtract/libxtract.h	Tue Dec 12 21:47:42 2006 +0000
+++ b/xtract/libxtract.h	Fri Dec 15 21:17:12 2006 +0000
@@ -53,7 +53,7 @@
   * @{
   */
 
-#define XTRACT_FEATURES 44
+#define XTRACT_FEATURES 45
     
 #define LOG_LIMIT 10e-10
 #define VERY_BIG_NUMBER 2e10
@@ -89,9 +89,10 @@
     ODD_EVEN_RATIO,
     SHARPNESS,
     SLOPE,
-    LOWEST_MATCH,
+    LOWEST,
     HPS,
     F0,
+    FAILSAFE_F0,
     FLUX,
     ATTACK_TIME,
     DECAY_TIME,
@@ -178,7 +179,7 @@
  * 
  */
 #ifdef XTRACT
-extern int(*xtract[XTRACT_FEATURES])(float *data, int N, void *argv, float *result);
+extern int(*xtract[XTRACT_FEATURES])(const float *data, const int N, const void *argv, float *result);
 
 /** \brief An array of pointers to function help strings
  *
--- a/xtract/xtract_delta.h	Tue Dec 12 21:47:42 2006 +0000
+++ b/xtract/xtract_delta.h	Fri Dec 15 21:17:12 2006 +0000
@@ -30,20 +30,20 @@
 #include "xtract_types.h"
 
 /* \brief Extract spectral flux as defined by Gaƫl Richard (2006)*/
-int xtract_flux(float *data, int N, void *argv , float *result);
+int xtract_flux(const float *data, const int N, const void *argv , float *result);
 /*xtract_frame_tracker *xf */
 
 /** \brief Extract attack Time */
-int xtract_attack_time(float *data, int N, void *argv , float *result);
+int xtract_attack_time(const float *data, const int N, const void *argv , float *result);
 /* xtract_amp_tracker *xa */
 
 /** Extract temporal decrease */
-int xtract_decay_time(float *data, int N, void *argv, float *result);
+int xtract_decay_time(const float *data, const int N, const void *argv, float *result);
 /* xtract_amp_tracker *xa */
 
 
 /** \brief A generic function to calculate the delta of a feature over a given period (in frames) */
-int xtract_delta_feature(float *data, int N, void *argv, float *result);
+int xtract_delta_feature(const float *data, const int N, const void *argv, float *result);
 /*xtract_frame_tracker *xf */
 /*float frames*/
 
--- a/xtract/xtract_scalar.h	Tue Dec 12 21:47:42 2006 +0000
+++ b/xtract/xtract_scalar.h	Fri Dec 15 21:17:12 2006 +0000
@@ -41,7 +41,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the mean of N values from the array pointed to by *data 
  */
-int xtract_mean(float *data, int N, void *argv, float *result);
+int xtract_mean(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the variance of an input vector
  * 
@@ -50,7 +50,7 @@
  * \param *argv: a pointer to a float representing the mean of the input vector
  * \param *result: the variance of N values from the array pointed to by *data
  */
-int xtract_variance(float *data, int N, void *argv, float *result);
+int xtract_variance(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the deviation of an input vector
  * 
@@ -59,7 +59,7 @@
  * \param *argv: a pointer to a float representing the variance of the input vector
  * \param *result: the deviation of N values from the array pointed to by *data
  */
-int xtract_standard_deviation(float *data, int N, void *argv, float *result);
+int xtract_standard_deviation(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the average deviation of an input vector
  * 
@@ -68,7 +68,7 @@
  * \param *argv: a pointer to a float representing the mean of the input vector
  * \param *result: the  average deviation of N values from the array pointed to by *data
  */
-int xtract_average_deviation(float *data, int N, void *argv, float *result);
+int xtract_average_deviation(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the skewness of an input vector
  * 
@@ -77,7 +77,7 @@
  * \param *argv: a pointer to an array of floats representing the mean and standard deviation of the input vector
  * \param *result: the skewness of N values from the array pointed to by *data
  */
-int xtract_skewness(float *data, int N, void *argv,  float *result);
+int xtract_skewness(const float *data, const int N, const void *argv,  float *result);
 
 /** \brief Extract the kurtosis of an input vector
  * 
@@ -86,7 +86,7 @@
  * \param *argv: a pointer to an array of values representing the mean and standard deviation of the input vector
  * \param *result: the kurtosis of N values from the array pointed to by *data
  */
-int xtract_kurtosis(float *data, int N, void *argv,  float *result);
+int xtract_kurtosis(const float *data, const int N, const void *argv,  float *result);
 
 /** \brief Extract the centroid of an input vector
  * 
@@ -95,7 +95,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the centroid of the values pointed to by *data
  */
-int xtract_centroid(float *data, int N, void *argv,  float *result);
+int xtract_centroid(const float *data, const int N, const void *argv,  float *result);
 
 /** \brief Calculate the Irregularity of an input vector using a method described by Krimphoff (1994)
  * 
@@ -104,7 +104,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the irregularity of N values from the array pointed to by *data
  */
-int xtract_irregularity_k(float *data, int N, void *argv, float *result);
+int xtract_irregularity_k(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Calculate the Irregularity of an input vector using a method described by Jensen (1999)
  * 
@@ -113,7 +113,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the irregularity of N values from the array pointed to by *data
  */
-int xtract_irregularity_j(float *data, int N, void *argv, float *result);
+int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Calculate the Tristimulus of an input vector using a method described by Pollard and Jansson (1982)
  * 
@@ -125,18 +125,18 @@
  * These three functions provide the first, second and third order tristimulus formulae
  * 
  */
-int xtract_tristimulus_1(float *data, int N, void *argv, float *result);
-int xtract_tristimulus_2(float *data, int N, void *argv, float *result);
-int xtract_tristimulus_3(float *data, int N, void *argv, float *result);
+int xtract_tristimulus_1(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 xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the smoothness of an input vector using a method described by McAdams (1999)
  * 
  * \param *data: a pointer to the first element in an array of floats representing the magnitude spectrum of an audio vector
  * \param N: the number of elements to be considered
- * \param *argv: a pointer to NULL
+ * \param *argv: a pointer to the first element of an array of integers containing the lower bound, upper bound, and pre-scaling factor, whereby array data in the range lower < n < upper will be pre-scaled by p before processing. 
  * \param *result: the smoothness of N values from the array pointed to by *data
  */
-int xtract_smoothness(float *data, int N, void *argv, float *result);
+int xtract_smoothness(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the spectral spread of an input vector using a method described by Casagrande(2005)
  * 
@@ -145,7 +145,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the spectral spread of N values from the array pointed to by *data
  */
-int xtract_spread(float *data, int N, void *argv, float *result);
+int xtract_spread(const float *data, const int N, const void *argv, float *result);
 
 /* Zero crossing rate */
 
@@ -156,7 +156,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the zero crossing rate of N values from the array pointed to by *data
  */
-int xtract_zcr(float *data, int N, void *argv, float *result);
+int xtract_zcr(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the spectral rolloff of an input vector using a method described by Bee Suan Ong (2005)
  * 
@@ -165,7 +165,7 @@
  * \param *argv: a pointer to an array containing a floating point value representing the threshold for rolloff, i.e. the percentile at which the rolloff is determined, expressed in the range 0-1.0, and a float representing the sample rate in Hz
  * \param *result: the spectral rolloff in Hz of N values from the array pointed to by *data. This is the point in the spectrum below which argv[0] of the energy is distributed.
  */
-int xtract_rolloff(float *data, int N, void *argv, float *result);
+int xtract_rolloff(const float *data, const int N, const void *argv, float *result);
 
 /* Loudness */
 /* A set of BARK_BANDS bark coefficients must be passed in, the loudness is calculated approximately according to Moore, Glasberg et al, 1997 */
@@ -177,7 +177,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the loudness of N values from the array pointed to by *data
  */
-int xtract_loudness(float *data, int N, void *argv, float *result);
+int xtract_loudness(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the spectral flatness measure of an input vector using a method described by Tristan Jehan (2005)
  * 
@@ -186,7 +186,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the spectral flatness of N values from the array pointed to by *data
  */
-int xtract_flatness(float *data, int N, void *argv, float *result);
+int xtract_flatness(const float *data, const int N, const void *argv, float *result);
 
 
 /** \brief Extract the tonality factor of an input vector using a method described by Tristan Jehan (2005)
@@ -196,7 +196,7 @@
  * \param *argv: a pointer to the spectral flatness measure of an audio vector (e.g. the output from xtract_flatness)
  * \param *result: the tonality factor of N values from the array pointed to by *data
  */
-int xtract_tonality(float *data, int N, void *argv, float *result);
+int xtract_tonality(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the noisiness of an input vector using a method described by Tae Hong Park (2000)
  * 
@@ -205,7 +205,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the noisiness of N values from the array pointed to by *data
  */
-int xtract_noisiness(float *data, int N, void *argv, float *result);
+int xtract_noisiness(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the RMS amplitude of an input vector using a method described by Tae Hong Park (2000)
  * 
@@ -214,7 +214,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the RMS amplitude of N values from the array pointed to by *data
  */
-int xtract_rms_amplitude(float *data, int N, void *argv, float *result);
+int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the Inharmonicity of an input vector 
  * 
@@ -223,7 +223,7 @@
  * \param *argv: a pointer to a float representing the fundamental frequency of the input vector.
  * \param *result: the inharmonicity of N values from the array pointed to by *data
  */
-int xtract_inharmonicity(float *data, int N, void *argv, float *result);
+int xtract_inharmonicity(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the spectral crest of an input vector using a method described by Peeters (2003)
  * 
@@ -232,7 +232,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the spectral crest of N values from the array pointed to by *data
  */
-int xtract_crest(float *data, int N, void *argv, float *result);
+int xtract_crest(const float *data, const int N, const void *argv, float *result);
     
 /** \brief Extract the Spectral Power of an input vector using a method described by Bee Suan Ong (2005)
  * 
@@ -241,7 +241,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the spectral power of N values from the array pointed to by *data
  */
-int xtract_power(float *data, int N, void *argv, float *result);
+int xtract_power(const float *data, const int N, const void *argv, float *result);
     
 /* Odd to even harmonic ratio */
 /** \brief Extract the Odd to even harmonic ratio of an input vector 
@@ -251,7 +251,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the odd/even harmonic ratio of N values from the array pointed to by *data
  */
-int xtract_odd_even_ratio(float *data, int N, void *argv, float *result);
+int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the Sharpness of an input vector 
  * 
@@ -260,7 +260,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the Sharpness of N values from the array pointed to by *data
  */
-int xtract_sharpness(float *data, int N, void *argv, float *result);
+int xtract_sharpness(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the Slope of an input vector 
  * 
@@ -269,17 +269,17 @@
  * \param *argv: a pointer to NULL
  * \param *result: the Slope of N values from the array pointed to by *data
  */
-int xtract_slope(float *data, int N, void *argv, float *result);
+int xtract_slope(const float *data, const int N, const void *argv, float *result);
 
-/** \brief Extract the value of the first partial in an input vector that closely matches a certain 'guess'
+/** \brief Extract the value of the lowest value in an input vector that between two bounds
  * 
- * \param *data: a pointer to the first element in an array of floats that represents the frequencies of the spectral peaks of an audio vector
+ * \param *data: a pointer to the first element in an array of floats
  * \param N: the number of elements to be considered
- * \param *argv: a pointer to a float value representing the guess
- * \param *result: the F0 of N values from the array pointed to by *data
+ * \param *argv: a pointer to an array containing a lower and upper bounds for search, where lower < n < upper.
+ * \param *result: a pointer to a value representing the lowest non-zero component in *data. If no match is found then -0 is returned.
  * 
- * This method takes a guess which can come from taking the ZCR of an autocorrelation function, and then finds the spectral peak that most closely matches the gess */
-int xtract_lowest_match(float *data, int N, void *argv, float *result);
+ */
+int xtract_lowest(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the Pitch of an input vector using Harmonic Product Spectrum (HPS) analysis
  * 
@@ -290,7 +290,7 @@
  * \param *argv: a pointer to NULL
  * \param *result: the pitch of N values from the array pointed to by *data
  */
-int xtract_hps(float *data, int N, void *argv, float *result);
+int xtract_hps(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the fundamental frequency of an input vector 
  * 
@@ -302,7 +302,19 @@
  * This algorithm is based on the AMDF, with peak and centre clipping. It would benefit from further improvements to improve noise robustness and overall efficiency
  * 
  */
-int xtract_f0(float *data, int N, void *argv, float *result);
+int xtract_f0(const float *data, const int N, const void *argv, float *result);
+
+/** \brief Extract the fundamental frequency of an input vector 
+ * 
+ * \param *data: a pointer to the first element in an array of floats representing an audio vector 
+ * \param N: the number of elements to be considered
+ * \param *argv: a pointer to a float representing the audio sample rate
+ * \param *result: the pitch of N values from the array pointed to by *data
+ *
+ * This function wraps xtract_f0, but provides the frequency of the lowest partial in the peak spectrum if f0 can't be found.
+ *  
+ */
+int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result);
 
 /** @} */
 
--- a/xtract/xtract_vector.h	Tue Dec 12 21:47:42 2006 +0000
+++ b/xtract/xtract_vector.h	Fri Dec 15 21:17:12 2006 +0000
@@ -41,7 +41,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the magnitude spectrum of N values from the array pointed to by *data 
  */
-int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result);
+int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract autocorrelation from time domain signal using FFT based method
  * 
@@ -50,7 +50,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the autocorrelation of N values from the array pointed to by *data 
  */
-int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result);
+int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract Mel Frequency Cepstral Coefficients based on a method described by Rabiner
  * 
@@ -61,7 +61,7 @@
  * 
  * The data structure pointed to by *argv must be obtained by first calling xtract_init_mfcc
  */
-int xtract_mfcc(float *data, int N, void *argv, float *result);
+int xtract_mfcc(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the Discrete Cosine transform of a time domain signal
  * \param *data: a pointer to the first element in an array of floats representing an audio vector
@@ -69,7 +69,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: a pointer to an array containing resultant dct coefficients
  */
-int xtract_dct(float *data, int N, void *argv, float *result);
+int xtract_dct(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract autocorrelation from time domain signal using time-domain autocorrelation technique 
  * 
@@ -78,7 +78,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the autocorrelation of N values from the array pointed to by *data 
  */
-int xtract_autocorrelation(float *data, int N, void *argv, float *result);
+int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract Average Magnitude Difference Function from time domain signal 
  * 
@@ -87,7 +87,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the AMDF of N values from the array pointed to by *data 
  */
-int xtract_amdf(float *data, int N, void *argv, float *result);
+int xtract_amdf(const float *data, const int N, const void *argv, float *result);
     
 /** \brief Extract Average Squared Difference Function from time domain signal 
  * 
@@ -96,7 +96,7 @@
  * \param *argv: a pointer to NULL 
  * \param *result: the ASDF of N values from the array pointed to by *data 
  */
-int xtract_asdf(float *data, int N, void *argv, float *result);
+int xtract_asdf(const float *data, const int N, const void *argv, float *result);
     
 /** \brief Extract Bark band coefficients based on a method   
  * \param *data: a pointer to the first element in an array of floats representing the magnitude spectrum of an audio vector
@@ -107,7 +107,7 @@
  * The limits array pointed to by *argv must be obtained by first calling xtract_init_bark
  * 
  */
-int xtract_bark_coefficients(float *data, int N, void *argv, float *result);
+int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the frequency and amplitude of spectral peaks from a magnitude spectrum
  * \param *data: a pointer to the first element in an array of floats representing the magnitude spectrum of an audio vector
@@ -115,7 +115,7 @@
  * \param *argv: a pointer to an array containing peak threshold as percentage below max peak, and sample rate 
  * \param *result: a pointer to an array of size N, containing N/2 freqs and N/2 amplitudes, amplitudes are on a decibel scale with dbFS = 0 
  */
-int xtract_peaks(float *data, int N, void *argv, float *result);
+int xtract_peaks(const float *data, const int N, const void *argv, float *result);
 
 /** \brief Extract the harmonic spectrum of from a of a peak spectrum 
  * \param *data: a pointer to the first element in an array of floats representing the peak spectrum of an audio vector (e.g. *result from  xtract_peaks). It is expected that the first half of the array pointed to by *data will contain frequencies for each peak considered, and the the second half will contain the respective amplitudes
@@ -123,7 +123,7 @@
  * \param *argv: a pointer to an array containing the fundamental (f0) of the spectrum, and a threshold (t) where 0<=t<=1.0, and t determines the distance from the nearest harmonic number within which a partial can be considered harmonic.
  * \param *result: a pointer to an array of size N containing N/2 freqs and N/2 amplitudes, amplitudes are on a decibel scale with dbFS = 0
  */
-int xtract_harmonics(float *data, int N, void *argv, float *result);
+int xtract_harmonics(const float *data, const int N, const void *argv, float *result);
 
 /** @} */