changeset 45:e8f4c56de591

Added new features: sum, highest_value, crest and noisiness
author Jamie Bullock <jamie@postlude.co.uk>
date Wed, 20 Dec 2006 15:34:56 +0000
parents b2e7e24c9a9c
children 4725bee447c2
files examples/puredata/xtract~.c src/libxtract.c src/scalar.c src/vector.c xtract/libxtract.h xtract/xtract_macros.h xtract/xtract_scalar.h xtract/xtract_vector.h
diffstat 8 files changed, 121 insertions(+), 54 deletions(-) [+]
line wrap: on
line diff
--- a/examples/puredata/xtract~.c	Wed Dec 20 12:28:08 2006 +0000
+++ b/examples/puredata/xtract~.c	Wed Dec 20 15:34:56 2006 +0000
@@ -140,8 +140,11 @@
     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 @@
 	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 @@
 	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:
--- a/src/libxtract.c	Wed Dec 20 12:28:08 2006 +0000
+++ b/src/libxtract.c	Wed Dec 20 15:34:56 2006 +0000
@@ -51,7 +51,9 @@
     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 @@
    "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",
--- a/src/scalar.c	Wed Dec 20 12:28:08 2006 +0000
+++ b/src/scalar.c	Wed Dec 20 15:34:56 2006 +0000
@@ -320,11 +320,11 @@
     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 @@
 
     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_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,26 +451,45 @@
 
 }
 
-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;
+
+    *result = data[N];
+
+    while(n--){
+       if((temp = data[n]) > *(float *)argv)	
+	    *result = MIN(*result, data[n]);
+    }
+
+    return SUCCESS;
+}
+
+int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
+
     int n = N;
 
-    lower = *(float *)argv;
-    upper = *((float *)argv+1);
+    *result = data[N];
 
-    lowest = upper;
-
-    while(n--) {
-	if(data[n] > lower)
-	    *result = MIN(lowest, data[n]);
-    }
-
-    *result = (*result == upper ? -0 : *result);
+    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){
 
     int n = N, M, m, l, peak_index, position1_lwr;
@@ -599,8 +638,7 @@
 	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);
--- a/src/vector.c	Wed Dec 20 12:28:08 2006 +0000
+++ b/src/vector.c	Wed Dec 20 15:34:56 2006 +0000
@@ -245,8 +245,8 @@
         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 @@
     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 @@
     }
 
     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 @@
     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{
--- a/xtract/libxtract.h	Wed Dec 20 12:28:08 2006 +0000
+++ b/xtract/libxtract.h	Wed Dec 20 15:34:56 2006 +0000
@@ -53,13 +53,8 @@
   * @{
   */
 
-#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 @@
     ODD_EVEN_RATIO,
     SHARPNESS,
     SLOPE,
-    LOWEST,
+    LOWEST_VALUE,
+    HIGHEST_VALUE,
+    SUM,
     HPS,
     F0,
     FAILSAFE_F0,
--- a/xtract/xtract_macros.h	Wed Dec 20 12:28:08 2006 +0000
+++ b/xtract/xtract_macros.h	Wed Dec 20 15:34:56 2006 +0000
@@ -36,6 +36,13 @@
 #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
--- a/xtract/xtract_scalar.h	Wed Dec 20 12:28:08 2006 +0000
+++ b/xtract/xtract_scalar.h	Wed Dec 20 15:34:56 2006 +0000
@@ -271,15 +271,35 @@
  */
 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
  * 
--- a/xtract/xtract_vector.h	Wed Dec 20 12:28:08 2006 +0000
+++ b/xtract/xtract_vector.h	Wed Dec 20 15:34:56 2006 +0000
@@ -112,16 +112,18 @@
 /** \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);