aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJamie Bullock <jamie@postlude.co.uk>2006-12-20 15:34:56 +0000
committerJamie Bullock <jamie@postlude.co.uk>2006-12-20 15:34:56 +0000
commit46ee1ba4b2e3eda3e14abfc969356f6dcb0c6dc0 (patch)
tree33d043207bb8845ef9cd6a9f6c6a99cfd55a35fa
parente5051b14a4642a6a6c6097c0ae24ecdfa53594e9 (diff)
downloadLibXtract-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~.c14
-rw-r--r--src/libxtract.c8
-rw-r--r--src/scalar.c76
-rw-r--r--src/vector.c19
-rw-r--r--xtract/libxtract.h11
-rw-r--r--xtract/xtract_macros.h7
-rw-r--r--xtract/xtract_scalar.h28
-rw-r--r--xtract/xtract_vector.h8
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);