diff options
author | Jamie Bullock <jamie@postlude.co.uk> | 2006-12-20 15:34:56 +0000 |
---|---|---|
committer | Jamie Bullock <jamie@postlude.co.uk> | 2006-12-20 15:34:56 +0000 |
commit | 46ee1ba4b2e3eda3e14abfc969356f6dcb0c6dc0 (patch) | |
tree | 33d043207bb8845ef9cd6a9f6c6a99cfd55a35fa | |
parent | e5051b14a4642a6a6c6097c0ae24ecdfa53594e9 (diff) | |
download | LibXtract-46ee1ba4b2e3eda3e14abfc969356f6dcb0c6dc0.tar.gz LibXtract-46ee1ba4b2e3eda3e14abfc969356f6dcb0c6dc0.tar.bz2 LibXtract-46ee1ba4b2e3eda3e14abfc969356f6dcb0c6dc0.zip |
Added new features: sum, highest_value, crest and noisiness
-rw-r--r-- | examples/puredata/xtract~.c | 14 | ||||
-rw-r--r-- | src/libxtract.c | 8 | ||||
-rw-r--r-- | src/scalar.c | 76 | ||||
-rw-r--r-- | src/vector.c | 19 | ||||
-rw-r--r-- | xtract/libxtract.h | 11 | ||||
-rw-r--r-- | xtract/xtract_macros.h | 7 | ||||
-rw-r--r-- | xtract/xtract_scalar.h | 28 | ||||
-rw-r--r-- | xtract/xtract_vector.h | 8 |
8 files changed, 119 insertions, 52 deletions
diff --git a/examples/puredata/xtract~.c b/examples/puredata/xtract~.c index 3e855c7..93c7617 100644 --- a/examples/puredata/xtract~.c +++ b/examples/puredata/xtract~.c @@ -140,8 +140,11 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) { else if(tmp == gensym("sharpness")) x->feature = SHARPNESS; else if(tmp == gensym("slope")) x->feature = SLOPE; else if(tmp == gensym("f0")) x->feature = F0; + else if(tmp == gensym("failsafe_f0")) x->feature = FAILSAFE_F0; else if(tmp == gensym("hps"))x->feature = HPS; - else if(tmp == gensym("lowest"))x->feature = LOWEST; + else if(tmp == gensym("lowest_value"))x->feature = LOWEST_VALUE; + else if(tmp == gensym("highest_value"))x->feature = HIGHEST_VALUE; + else if(tmp == gensym("sum"))x->feature = SUM; else if(tmp == gensym("dct")) x->feature = DCT; else if(tmp == gensym("magnitude_spectrum")) x->feature = MAGNITUDE_SPECTRUM; @@ -170,14 +173,16 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) { case INHARMONICITY: case ODD_EVEN_RATIO: case F0: + case FAILSAFE_F0: case TONALITY: floatargs = 1; break; case SKEWNESS: case KURTOSIS: case PEAKS: - case LOWEST: case HARMONICS: + case NOISINESS: + case CREST: floatargs = 2; break; case CENTROID: @@ -191,8 +196,9 @@ static void *xtract_new(t_symbol *me, t_int argc, t_atom *argv) { case SPREAD: case ZCR: case LOUDNESS: - case CREST: - case NOISINESS: + case LOWEST_VALUE: + case HIGHEST_VALUE: + case SUM: case RMS_AMPLITUDE: case POWER: case SHARPNESS: diff --git a/src/libxtract.c b/src/libxtract.c index 11faeee..f729ccf 100644 --- a/src/libxtract.c +++ b/src/libxtract.c @@ -51,7 +51,9 @@ int(*xtract[])(const float *, const int, const void *, float *) = { xtract_odd_even_ratio, xtract_sharpness, xtract_slope, - xtract_lowest, + xtract_lowest_value, + xtract_highest_value, + xtract_sum, xtract_hps, xtract_f0, xtract_failsafe_f0, @@ -101,7 +103,9 @@ char *xtract_help_strings[] = { "xtract_odd_even_ratio", "xtract_sharpness", "xtract_slope", - "xtract_lowest", + "xtract_lowest_value", + "xtract_highest_value", + "xtract_sum", "xtract_hps", "xtract_f0", "xtract_failsafe_f0", diff --git a/src/scalar.c b/src/scalar.c index 02f0f18..c7d6edd 100644 --- a/src/scalar.c +++ b/src/scalar.c @@ -320,11 +320,11 @@ int xtract_flatness(const float *data, const int N, const void *argv, float *res num = pow(num, 1.f / N); den /= N; - if(num < 1e-20) - num = 1e-20; + if(num < VERY_SMALL_NUMBER) + num = VERY_SMALL_NUMBER; - if(den < 1e-20) - den = 1e-20; + if(den < VERY_SMALL_NUMBER) + den = VERY_SMALL_NUMBER; *result = num / den; @@ -338,7 +338,7 @@ int xtract_tonality(const float *data, const int N, const void *argv, float *res sfm = *(float *)argv; - sfmdb = (sfm > 0 ? (10 * log10(sfm)) / -60 : 0); + sfmdb = (sfm > 0 ? ((10 * log10(sfm)) / -60) : 0); *result = MIN(sfmdb, 1); @@ -347,13 +347,33 @@ int xtract_tonality(const float *data, const int N, const void *argv, float *res int xtract_crest(const float *data, const int N, const void *argv, float *result){ - return FEATURE_NOT_IMPLEMENTED; + float max, mean; + + max = mean = 0.f; + + max = *(float *)argv; + mean = *((float *)argv+1); + + *result = max / mean; + + return SUCCESS; } int xtract_noisiness(const float *data, const int N, const void *argv, float *result){ - return FEATURE_NOT_IMPLEMENTED; + float h, i, p; /*harmonics, inharmonics, partials */ + + i = p = h = 0.f; + + h = *(float *)argv; + p = *((float *)argv+1); + + i = p - h; + + *result = i / p; + + return SUCCESS; } @@ -431,24 +451,43 @@ int xtract_slope(const float *data, const int N, const void *argv, float *result } -int xtract_lowest(const float *data, const int N, const void *argv, float *result){ +int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){ - float lower, upper, lowest; int n = N; + float temp; - lower = *(float *)argv; - upper = *((float *)argv+1); - - lowest = upper; + *result = data[N]; - while(n--) { - if(data[n] > lower) - *result = MIN(lowest, data[n]); + while(n--){ + if((temp = data[n]) > *(float *)argv) + *result = MIN(*result, data[n]); } - *result = (*result == upper ? -0 : *result); + return SUCCESS; +} + +int xtract_highest_value(const float *data, const int N, const void *argv, float *result){ + + int n = N; + + *result = data[N]; + + while(n--) + *result = MAX(*result, data[n]); + + return SUCCESS; +} + + +int xtract_sum(const float *data, const int N, const void *argv, float *result){ + + int n = N; + + while(n--) + *result += *data++; return SUCCESS; + } int xtract_hps(const float *data, const int N, const void *argv, float *result){ @@ -599,8 +638,7 @@ int xtract_failsafe_f0(const float *data, const int N, const void *argv, float * 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); + xtract_lowest_value(peaks, N >> 1, argf, result); free(magnitudes); free(peaks); diff --git a/src/vector.c b/src/vector.c index b0e42d5..3a6e587 100644 --- a/src/vector.c +++ b/src/vector.c @@ -245,8 +245,8 @@ int xtract_peaks(const float *data, const int N, const void *argv, float *result return_code = BAD_ARGV; } else{ - thresh = 0; - sr = 44100; + thresh = 0.f; + sr = 44100.f; } input = (float *)malloc(bytes = N * sizeof(float)); @@ -259,7 +259,7 @@ int xtract_peaks(const float *data, const int N, const void *argv, float *result M = N >> 1; width = sr / N; - y = y2 = y3 = p = max = 0; + y = y2 = y3 = p = max = 0.f; if(thresh < 0 || thresh > 100){ thresh = 0; @@ -267,19 +267,12 @@ int xtract_peaks(const float *data, const int N, const void *argv, float *result } if(!sr){ - sr = 44100; + sr = 44100.f; return_code = BAD_ARGV; } - while(n--){ + while(n--) max = MAX(max, input[n]); - /* ensure we never take log10(0) */ - /*input[n] = (input[n] < LOG_LIMIT ? LOG_LIMIT : input[n]);*/ - if ((input[n] * 100000) <= 1) - /* We get a more stable peak this way */ - input[n] = 1; - - } thresh *= .01 * max; @@ -289,7 +282,7 @@ int xtract_peaks(const float *data, const int N, const void *argv, float *result for(n = 1; n < M; n++){ 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[n] = width * (n + (p = .5 * (y = input[n-1] - (y3 = input[n+1])) / (input[n - 1] - 2 * (y2 = input[n]) + input[n + 1]))); result[M + n] = y2 - .25 * (y - y3) * p; } else{ diff --git a/xtract/libxtract.h b/xtract/libxtract.h index 7670c83..8c0dc40 100644 --- a/xtract/libxtract.h +++ b/xtract/libxtract.h @@ -53,13 +53,8 @@ extern "C" { * @{ */ -#define XTRACT_FEATURES 45 +#define XTRACT_FEATURES 47 -#define LOG_LIMIT 10e-10 -#define VERY_BIG_NUMBER 2e10 -#define SR_LIMIT 192000 -#define BARK_BANDS 26 - /** \brief Enumeration of features, elements are used as indixes to an array of pointers to feature extracton functions */ enum features_ { MEAN, @@ -89,7 +84,9 @@ enum features_ { ODD_EVEN_RATIO, SHARPNESS, SLOPE, - LOWEST, + LOWEST_VALUE, + HIGHEST_VALUE, + SUM, HPS, F0, FAILSAFE_F0, diff --git a/xtract/xtract_macros.h b/xtract/xtract_macros.h index 3ee97b2..f2a89b7 100644 --- a/xtract/xtract_macros.h +++ b/xtract/xtract_macros.h @@ -36,6 +36,13 @@ extern "C" { #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define NEEDS_FFTW printf("LibXtract must be compiled with fftw support to use this function.\n") +#define VERY_SMALL_NUMBER 1e-20 +#define LOG_LIMIT VERY_SMALL_NUMBER +#define VERY_BIG_NUMBER 1e20 +#define SR_LIMIT 192000 +#define BARK_BANDS 26 + + #ifdef __cplusplus } #endif diff --git a/xtract/xtract_scalar.h b/xtract/xtract_scalar.h index c4618fa..8d8c446 100644 --- a/xtract/xtract_scalar.h +++ b/xtract/xtract_scalar.h @@ -271,15 +271,35 @@ int xtract_sharpness(const float *data, const int N, const void *argv, float *re */ int xtract_slope(const float *data, const int N, const void *argv, float *result); -/** \brief Extract the value of the lowest value in an input vector that between two bounds +/** \brief Extract the value of the lowest value in an input 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 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. + * \param *argv: a pointer to a float representing the lower limit for the search. i.e. (*result > *argv) returns 1. + * \param *result: a pointer to a value representing the lowest component in *data that falls above a given threshold. * */ -int xtract_lowest(const float *data, const int N, const void *argv, float *result); +int xtract_lowest_value(const float *data, const int N, const void *argv, float *result); + +/** \brief Extract the value of the highest value in an input 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 NULL. + * \param *result: a pointer to a value representing the highest component in *data. + * + */ +int xtract_highest_value(const float *data, const int N, const void *argv, float *result); + +/** \brief Extract the sum of the values in an input 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 NULL. + * \param *result: a pointer to a value representing the sum of all of the values pointed to by *data. + * + */ +int xtract_sum(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 * diff --git a/xtract/xtract_vector.h b/xtract/xtract_vector.h index 215c782..92e908a 100644 --- a/xtract/xtract_vector.h +++ b/xtract/xtract_vector.h @@ -112,16 +112,18 @@ int xtract_bark_coefficients(const float *data, const int N, const void *argv, f /** \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 - * \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 + * \param *argv: a pointer to an array containing the peak threshold as percentage of the magnitude of the maximum peak found, and the sample rate in Hz. + * \param *result: a pointer to an array of size N, containing N/2 freqs and N/2 amplitudes + * */ + 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 * \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 + * \param *result: a pointer to an array of size N containing N/2 freqs and N/2 amplitudes. */ int xtract_harmonics(const float *data, const int N, const void *argv, float *result); |