diff options
-rw-r--r-- | ChangeLog | 5 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | examples/puredata/xtract~.c | 19 | ||||
-rw-r--r-- | src/delta.c | 11 | ||||
-rw-r--r-- | src/init.c | 4 | ||||
-rw-r--r-- | src/libxtract.c | 6 | ||||
-rw-r--r-- | src/scalar.c | 42 | ||||
-rw-r--r-- | src/vector.c | 46 | ||||
-rw-r--r-- | xtract/libxtract.h | 16 | ||||
-rw-r--r-- | xtract/xtract_macros.h | 1 | ||||
-rw-r--r-- | xtract/xtract_scalar.h | 6 | ||||
-rw-r--r-- | xtract/xtract_vector.h | 10 |
12 files changed, 139 insertions, 33 deletions
@@ -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; } @@ -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 |