aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--configure.in6
-rw-r--r--examples/puredata/xtract~.c19
-rw-r--r--src/delta.c11
-rw-r--r--src/init.c4
-rw-r--r--src/libxtract.c6
-rw-r--r--src/scalar.c42
-rw-r--r--src/vector.c46
-rw-r--r--xtract/libxtract.h16
-rw-r--r--xtract/xtract_macros.h1
-rw-r--r--xtract/xtract_scalar.h6
-rw-r--r--xtract/xtract_vector.h10
12 files changed, 139 insertions, 33 deletions
diff --git a/ChangeLog b/ChangeLog
index 003bfaa..6355511 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,9 @@
2006-11-10 Jamie Bullock <jamie@postlude.co.uk>
+ * version 0.3.0
+ * Corrected typos in scalar.c
+ * Added -Wall to CFLAGS and corrected problems relating to warnings
+ * Added xtract_harmonics and corresponding documentation
+2006-11-10 Jamie Bullock <jamie@postlude.co.uk>
* version 0.2.2
* Fixed 'bus error' crash on Mac OS X by adding 'extern' declarations
to xtract and xtract_help_strings
diff --git a/configure.in b/configure.in
index 8d25fe8..5942cba 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, 2)
+m4_define(libxtract_minor_version, 3)
# Increment for fixes
-m4_define(libxtract_fix_version, 2)
+m4_define(libxtract_fix_version, 0)
m4_define(libxtract_version, libxtract_major_version.libxtract_minor_version.libxtract_fix_version)
@@ -64,7 +64,7 @@ AC_ARG_ENABLE(simpletest,
# age to 0.
XTRACT_SO_VERSION=0:0:0
-CFLAGS="$CFLAGS -pedantic -ansi -Wall"
+CFLAGS="$CFLAGS -pedantic -ansi -Wall -std=c99"
LDFLAGS="$LDFLAGS -lm"
AC_ARG_WITH(pd_dir,
diff --git a/examples/puredata/xtract~.c b/examples/puredata/xtract~.c
index 958f8fc..05dc5e0 100644
--- a/examples/puredata/xtract~.c
+++ b/examples/puredata/xtract~.c
@@ -39,10 +39,14 @@ static t_int *xtract_perform(t_int *w) {
t_sample *in = (t_sample *)(w[1]);
t_xtract_tilde *x = (t_xtract_tilde *)(w[2]);
t_int N = (t_int)(w[3]);
+ t_int return_code = 0;
float result = 0;
- xtract[x->feature]((float *)in, N, x->argv, &result);
+ return_code = xtract[x->feature]((float *)in, N, x->argv, &result);
+ if(return_code == FEATURE_NOT_IMPLEMENTED)
+ pd_error(x, "Feature not implemented");
+
outlet_float(x->x_obj.ob_outlet, result);
return (w+4);
}
@@ -53,11 +57,15 @@ static t_int *xtract_perform_vector(t_int *w) {
t_float *tmp_in, *tmp_out;
t_xtract_tilde *x = (t_xtract_tilde *)(w[3]);
t_int N = (t_int)(w[4]), n;
+ t_int return_code = 0;
tmp_in = copybytes(in, N * sizeof(t_float));
tmp_out = getbytes(N * sizeof(t_float));
- xtract[x->feature](tmp_in, N, x->argv, tmp_out);
+ return_code = xtract[x->feature](tmp_in, N, x->argv, tmp_out);
+
+ if(return_code == FEATURE_NOT_IMPLEMENTED)
+ pd_error(x, "Feature not implemented");
n = N;
@@ -158,6 +166,10 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
80.0f, f->n_filters, f->filters);
}
else if(tmp == gensym("dct")) x->feature = DCT;
+ else if(tmp == gensym("harmonics")){
+ x->feature = HARMONICS;
+ x->argv = getbytes(3 * sizeof(t_float));
+ }
else if(tmp == gensym("bark_coefficients")){
x->feature = BARK_COEFFICIENTS;
x->argv = (t_int *)getbytes(BARK_BANDS * sizeof(t_int));
@@ -173,7 +185,8 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) {
if(x->feature == AUTOCORRELATION || x->feature == AUTOCORRELATION_FFT ||
x->feature == MFCC || x->feature == AMDF || x->feature == ASDF||
x->feature == DCT || x->feature == BARK_COEFFICIENTS ||
- x->feature == MAGNITUDE_SPECTRUM || x->feature == PEAKS)
+ x->feature == MAGNITUDE_SPECTRUM || x->feature == PEAKS ||
+ x->feature == HARMONICS)
x->feature_type = VECTOR;
else if (x->feature == FLUX || x->feature == ATTACK_TIME ||
diff --git a/src/delta.c b/src/delta.c
index c947c0a..b6259d6 100644
--- a/src/delta.c
+++ b/src/delta.c
@@ -20,30 +20,29 @@
/* xtract_delta.c: defines functions that extract a feature as a single value from more than one input vector */
-#include "xtract/xtract_delta.h"
-#include "xtract/xtract_macros.h"
+#include "xtract/libxtract.h"
int xtract_flux(float *data, int N, void *argv , float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_attack_time(float *data, int N, void *argv , float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_decay_time(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_delta_feature(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
diff --git a/src/init.c b/src/init.c
index 147528f..81810e9 100644
--- a/src/init.c
+++ b/src/init.c
@@ -112,7 +112,7 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_max, float freq
int xtract_init_bark(int N, float nyquist, int *band_limits){
- float bark_freq_max, bark_freq_min, freq_bw_bark, temp, 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)*/
+ 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)*/
int M, bands = BARK_BANDS;
@@ -121,4 +121,6 @@ int xtract_init_bark(int N, float nyquist, int *band_limits){
while(bands--)
band_limits[bands] = edges[bands] / nyquist * M;
/*FIX shohuld use rounding, but couldn't get it to work */
+
+ return SUCCESS;
}
diff --git a/src/libxtract.c b/src/libxtract.c
index 63abe49..a749d96 100644
--- a/src/libxtract.c
+++ b/src/libxtract.c
@@ -68,7 +68,8 @@ int(*xtract[])(float *, int, void *, float *) = {
xtract_magnitude_spectrum,
xtract_autocorrelation_fft,
xtract_mfcc,
- xtract_dct
+ xtract_dct,
+ xtract_harmonics
};
char *xtract_help_strings[] = {
@@ -114,5 +115,6 @@ char *xtract_help_strings[] = {
"xtract_magnitude_spectrum",
"xtract_autocorrelation_fft",
"xtract_mfcc",
- "xtract_dct"
+ "xtract_dct",
+ "xtract_harmonics"
};
diff --git a/src/scalar.c b/src/scalar.c
index b2bf0b0..cf453f9 100644
--- a/src/scalar.c
+++ b/src/scalar.c
@@ -33,6 +33,8 @@ int xtract_mean(float *data, int N, void *argv, float *result){
*result += *data++;
*result /= N;
+
+ return SUCCESS;
}
int xtract_variance(float *data, int N, void *argv, float *result){
@@ -43,12 +45,15 @@ int xtract_variance(float *data, int N, void *argv, float *result){
*result += *data++ - *(float *)argv;
*result = SQ(*result) / (N - 1);
+
+ return SUCCESS;
}
int xtract_standard_deviation(float *data, int N, void *argv, float *result){
*result = sqrt(*(float *)argv);
+ return SUCCESS;
}
int xtract_average_deviation(float *data, int N, void *argv, float *result){
@@ -60,6 +65,7 @@ int xtract_average_deviation(float *data, int N, void *argv, float *result){
*result /= N;
+ return SUCCESS;
}
int xtract_skewness(float *data, int N, void *argv, float *result){
@@ -71,6 +77,7 @@ int xtract_skewness(float *data, int N, void *argv, float *result){
*result = pow(*result, 3) / N;
+ return SUCCESS;
}
int xtract_kurtosis(float *data, int N, void *argv, float *result){
@@ -82,6 +89,7 @@ int xtract_kurtosis(float *data, int N, void *argv, float *result){
*result = pow(*result, 4) / N - 3;
+ return SUCCESS;
}
@@ -92,7 +100,7 @@ int xtract_centroid(float *data, int N, void *argv, float *result){
float *freqs, *amps, FA = 0.f, A = 0.f;
freqs = data;
- amps = data + (N >> 1);
+ amps = data + n;
while(n--){
FA += freqs[n] * amps[n];
@@ -101,6 +109,7 @@ int xtract_centroid(float *data, int N, void *argv, float *result){
*result = FA / A;
+ return SUCCESS;
}
int xtract_irregularity_k(float *data, int N, void *argv, float *result){
@@ -111,6 +120,7 @@ int xtract_irregularity_k(float *data, int N, void *argv, float *result){
for(n = 1; n < M; n++)
*result += abs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3);
+ return SUCCESS;
}
int xtract_irregularity_j(float *data, int N, void *argv, float *result){
@@ -126,6 +136,7 @@ int xtract_irregularity_j(float *data, int N, void *argv, float *result){
*result = num / den;
+ return SUCCESS;
}
int xtract_tristimulus_1(float *data, int N, void *argv, float *result){
@@ -139,6 +150,7 @@ int xtract_tristimulus_1(float *data, int N, void *argv, float *result){
*result = data[0] / den;
+ return SUCCESS;
}
int xtract_tristimulus_2(float *data, int N, void *argv, float *result){
@@ -152,6 +164,7 @@ int xtract_tristimulus_2(float *data, int N, void *argv, float *result){
*result = (data[1] + data[2] + data[3]) / den;
+ return SUCCESS;
}
int xtract_tristimulus_3(float *data, int N, void *argv, float *result){
@@ -167,6 +180,7 @@ int xtract_tristimulus_3(float *data, int N, void *argv, float *result){
*result = num / den;
+ return SUCCESS;
}
int xtract_smoothness(float *data, int N, void *argv, float *result){
@@ -181,6 +195,8 @@ int xtract_smoothness(float *data, int N, void *argv, float *result){
*result += abs(20 * log(data[n-1]) - (20 * log(data[n-2]) +
20 * log(data[n-1]) + 20 * log(data[n])) / 3);
}
+
+ return SUCCESS;
}
int xtract_spread(float *data, int N, void *argv, float *result){
@@ -197,6 +213,7 @@ int xtract_spread(float *data, int N, void *argv, float *result){
*result = sqrt(num / den);
+ return SUCCESS;
}
int xtract_zcr(float *data, int N, void *argv, float *result){
@@ -208,6 +225,7 @@ int xtract_zcr(float *data, int N, void *argv, float *result){
*result /= N;
+ return SUCCESS;
}
int xtract_rolloff(float *data, int N, void *argv, float *result){
@@ -223,6 +241,7 @@ int xtract_rolloff(float *data, int N, void *argv, float *result){
*result = n;
+ return SUCCESS;
}
int xtract_loudness(float *data, int N, void *argv, float *result){
@@ -233,6 +252,8 @@ int xtract_loudness(float *data, int N, void *argv, float *result){
while(n--)
*result += pow(data[n], 0.23);
+
+ return SUCCESS;
}
@@ -254,6 +275,7 @@ int xtract_flatness(float *data, int N, void *argv, float *result){
*result = 10 * log10(num / den);
+ return SUCCESS;
}
int xtract_tonality(float *data, int N, void *argv, float *result){
@@ -266,17 +288,18 @@ int xtract_tonality(float *data, int N, void *argv, float *result){
*result = MIN(sfmdb, 1);
+ return SUCCESS;
}
int xtract_crest(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_noisiness(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
@@ -288,6 +311,7 @@ int xtract_rms_amplitude(float *data, int N, void *argv, float *result){
*result = sqrt(*result / N);
+ return SUCCESS;
}
int xtract_inharmonicity(float *data, int N, void *argv, float *result){
@@ -306,18 +330,19 @@ int xtract_inharmonicity(float *data, int N, void *argv, float *result){
*result = (2 * num) / (*fund * den);
+ return SUCCESS;
}
int xtract_power(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){
- int n = N >> 1, j, k;
+ int n = N, j, k;
float num = 0.f, den = 0.f;
@@ -330,17 +355,18 @@ int xtract_odd_even_ratio(float *data, int N, void *argv, float *result){
*result = num / den;
+ return SUCCESS;
}
int xtract_sharpness(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
int xtract_slope(float *data, int N, void *argv, float *result){
- NOT_IMPLEMENTED;
+ return FEATURE_NOT_IMPLEMENTED;
}
@@ -356,6 +382,7 @@ int xtract_lowest_match(float *data, int N, void *argv, float *result){
*result = (lowest_match == SR_LIMIT ? 0 : lowest_match);
+ return SUCCESS;
}
int xtract_hps(float *data, int N, void *argv, float *result){
@@ -416,6 +443,7 @@ int xtract_hps(float *data, int N, void *argv, float *result){
free(coeffs3);
free(product);
+ return SUCCESS;
}
diff --git a/src/vector.c b/src/vector.c
index 657a7ef..8a656cb 100644
--- a/src/vector.c
+++ b/src/vector.c
@@ -51,6 +51,7 @@ int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
fftwf_destroy_plan(plan);
fftwf_free(temp);
+ return SUCCESS;
}
int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
@@ -69,13 +70,14 @@ int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
fftwf_destroy_plan(plan);
fftwf_free(temp);
+
+ return SUCCESS;
}
int xtract_mfcc(float *data, int N, void *argv, float *result){
xtract_mel_filter *f;
int n, filter;
- fftwf_plan plan;
f = (xtract_mel_filter *)argv;
@@ -91,6 +93,7 @@ int xtract_mfcc(float *data, int N, void *argv, float *result){
xtract_dct(result, f->n_filters, NULL, result);
+ return SUCCESS;
}
int xtract_dct(float *data, int N, void *argv, float *result){
@@ -102,6 +105,8 @@ int xtract_dct(float *data, int N, void *argv, float *result){
fftwf_execute(plan);
fftwf_destroy_plan(plan);
+
+ return SUCCESS;
}
#else
@@ -147,6 +152,8 @@ int xtract_autocorrelation(float *data, int N, void *argv, float *result){
}
result[n] = corr / N;
}
+
+ return SUCCESS;
}
int xtract_amdf(float *data, int N, void *argv, float *result){
@@ -164,6 +171,8 @@ int xtract_amdf(float *data, int N, void *argv, float *result){
}
result[n] = md / N;
}
+
+ return SUCCESS;
}
int xtract_asdf(float *data, int N, void *argv, float *result){
@@ -180,6 +189,8 @@ int xtract_asdf(float *data, int N, void *argv, float *result){
}
result[n] = sd / N;
}
+
+ return SUCCESS;
}
int xtract_bark_coefficients(float *data, int N, void *argv, float *result){
@@ -192,12 +203,14 @@ int xtract_bark_coefficients(float *data, int N, void *argv, float *result){
for(n = limits[band]; n < limits[band + 1]; n++)
result[band] += data[n];
}
+
+ return SUCCESS;
}
int xtract_peaks(float *data, int N, void *argv, float *result){
float thresh, max, y, y2, y3, p, width, sr;
- int n = N, M, return_code;
+ int n = N, M, return_code = SUCCESS;
if(argv != NULL){
thresh = ((float *)argv)[0];
@@ -259,3 +272,32 @@ int xtract_peaks(float *data, int N, void *argv, float *result){
return (return_code ? return_code : SUCCESS);
}
+int xtract_harmonics(float *data, int N, void *argv, float *result){
+
+ int n = (N >> 1), M = n;
+
+ float *freqs, *amps, f0, thresh, ratio, nearest, distance;
+
+ freqs = data;
+ amps = data + n;
+ f0 = *((float *)argv);
+ thresh = *((float *)argv+1);
+
+ ratio = nearest = distance = 0.f;
+
+ while(n--){
+ if(freqs[n]){
+ ratio = freqs[n] / f0;
+ nearest = round(ratio);
+ distance = fabs(nearest - ratio);
+ if(distance > thresh)
+ result[n] = result[M + n] = 0.f;
+ else
+ result[n] = result[M + n] = freqs[n];
+ }
+ else
+ result[n] = result[M + n] = 0.f;
+ }
+ return SUCCESS;
+}
+
diff --git a/xtract/libxtract.h b/xtract/libxtract.h
index 6e76ff3..489cddf 100644
--- a/xtract/libxtract.h
+++ b/xtract/libxtract.h
@@ -53,7 +53,7 @@ extern "C" {
* @{
*/
-#define XTRACT_FEATURES 43
+#define XTRACT_FEATURES 44
#define LOG_LIMIT 10e-10
#define VERY_BIG_NUMBER 2e10
@@ -104,7 +104,8 @@ enum features_ {
MAGNITUDE_SPECTRUM,
AUTOCORRELATION_FFT,
MFCC,
- DCT
+ DCT,
+ HARMONICS
};
/** \brief Enumeration of feature types */
@@ -126,7 +127,8 @@ enum return_codes_ {
MALLOC_FAILED,
BAD_ARGV,
BAD_VECTOR_SIZE,
- NO_RESULT
+ NO_RESULT,
+ FEATURE_NOT_IMPLEMENTED
};
/**
@@ -178,12 +180,18 @@ printf("Mean = %.2f\n", mean);
#ifdef XTRACT
extern int(*xtract[XTRACT_FEATURES])(float *data, int N, void *argv, float *result);
-
/** \brief An array of pointers to function help strings
*
* Defined in libxtract.c. As a minimum this will contain pointers to the names of all of the feature extraction functions in the library. This is intended as a 'quick reference' to be queried as necessary.
*/
extern char *xtract_help_strings[XTRACT_FEATURES];
+
+/** \brief An array of pointers to strings giving function output units
+ *
+ * Defined in libxtract.c. This contains pointers to strings giving the output units of all of the feature extraction functions in the library. This is intended as a 'quick reference' to be queried as necessary.
+ */
+extern char *xtract_units[XTRACT_FEATURES];
+
#endif
/** \brief A structure to store a set of n_filters Mel filters */
diff --git a/xtract/xtract_macros.h b/xtract/xtract_macros.h
index 534e1af..3ee97b2 100644
--- a/xtract/xtract_macros.h
+++ b/xtract/xtract_macros.h
@@ -34,7 +34,6 @@ extern "C" {
#define SQ(a) ((a) * (a))
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define MAX(a, b) ((a) > (b) ? (a) : (b))
-#define NOT_IMPLEMENTED printf("Feature not implemented yet.\n")
#define NEEDS_FFTW printf("LibXtract must be compiled with fftw support to use this function.\n")
#ifdef __cplusplus
diff --git a/xtract/xtract_scalar.h b/xtract/xtract_scalar.h
index 59c92dc..eae8afc 100644
--- a/xtract/xtract_scalar.h
+++ b/xtract/xtract_scalar.h
@@ -117,7 +117,7 @@ int xtract_irregularity_j(float *data, int N, void *argv, float *result);
/** \brief Calculate the Tristimulus of an input vector using a method described by Pollard and Jansson (1982)
*
- * \param *data: a pointer to the first element in an array of floats representing the amplitudes of the harmonic spectrum of an audio vector
+ * \param *data: a pointer to the first element in an array of floats representing the amplitudes of the harmonic spectrum of an audio vector e.g. a pointer to the second half of the array pointed to by *result from xtract_harmonics()
* \param N: the number of elements to be considered
* \param *argv: a pointer to NULL
* \param *result: the tristimulus of N values from the array pointed to by *data
@@ -246,8 +246,8 @@ int xtract_power(float *data, int N, void *argv, float *result);
/* Odd to even harmonic ratio */
/** \brief Extract the Odd to even harmonic ratio of an input vector
*
- * \param *data: a pointer to the first element in an array of floats representing the harmonic spectrum of an audio vector
- * \param N: the number of elements to be considered
+ * \param *data: a pointer to the first element in an array of floats representing the frequencies of the harmonic spectrum of an audio vector. It is sufficient to pass in a pointer to the array pointed to by *result from xtract_harmonics.
+ * \param N: the number of elements to be considered. If using the array pointed to by *result from xtract_harmonics, N should equal half the total array size i.e., just the frequencies of the peaks.
* \param *argv: a pointer to NULL
* \param *result: the odd/even harmonic ratio of N values from the array pointed to by *data
*/
diff --git a/xtract/xtract_vector.h b/xtract/xtract_vector.h
index d72d051..21cc8a3 100644
--- a/xtract/xtract_vector.h
+++ b/xtract/xtract_vector.h
@@ -109,7 +109,7 @@ int xtract_asdf(float *data, int N, void *argv, float *result);
*/
int xtract_bark_coefficients(float *data, int N, void *argv, float *result);
-/** \brief Extract the frequency and amplitude of spectral peaks from a of a magnitude spectrum
+/** \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
* \param N: the number of array elements to be considered
* \param *argv: a pointer to an array containing peak threshold as percentage below max peak, and sample rate
@@ -117,6 +117,14 @@ int xtract_bark_coefficients(float *data, int N, void *argv, float *result);
*/
int xtract_peaks(float *data, int N, 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
+ * \param N: the size of the array pointed to by *data
+ * \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);
+
/** @} */
#ifdef __cplusplus