diff options
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/descriptors.c | 57 | ||||
-rw-r--r-- | src/vector.c | 48 | ||||
-rw-r--r-- | xtract/libxtract.h | 7 | ||||
-rw-r--r-- | xtract/xtract_vector.h | 19 |
5 files changed, 110 insertions, 22 deletions
@@ -16,5 +16,4 @@ Use the fftw guru interface to create multipurpose global plans from xtract_fft_ Add LPC via Schur algorithm If argv uses an integer, then it should point to a variable of type int. At the moment floats are used to store ints. Write macro to truncate numbers <= 0 prior to taking log and integrate into functions across the library -Add xtract_chords() - gets pitch classes from spectrum either as MIDI note numbers or pitch class and octave class - e.g. 'F#4' etc. Add xtract_subbands() - gets subband power or subband magnitude for given bands diff --git a/src/descriptors.c b/src/descriptors.c index 4460de8..e96f467 100644 --- a/src/descriptors.c +++ b/src/descriptors.c @@ -86,7 +86,7 @@ xtract_function_descriptor_t *xtract_make_descriptors(void){ *argv_def = XTRACT_SR_DEFAULT; *argv_unit = XTRACT_HERTZ; break; - /* argc = 2 */; + /* argc = 2 */; case XTRACT_ROLLOFF: *argv_min = XTRACT_FFT_BANDS_MIN; *argv_max = XTRACT_FFT_BANDS_MAX; @@ -97,24 +97,6 @@ xtract_function_descriptor_t *xtract_make_descriptors(void){ *(argv_def + 1) = 95.f; *(argv_unit + 1) = XTRACT_PERCENT; break; - case XTRACT_SPECTRUM: - *argv_min = XTRACT_SR_LOWER_LIMIT / XTRACT_FFT_BANDS_MIN; - *argv_max = XTRACT_SR_UPPER_LIMIT / XTRACT_FFT_BANDS_MAX; - *argv_def = XTRACT_SR_DEFAULT / XTRACT_FFT_BANDS_DEF; - *argv_unit = XTRACT_HERTZ; - *(argv_min + 1) = 0; - *(argv_max + 1) = 3 ; - *(argv_def + 1) = 0; - *(argv_unit + 1) = XTRACT_NONE; - *(argv_min + 2) = 0; - *(argv_max + 2) = 1; - *(argv_def + 2) = 0; - *(argv_unit + 2) = XTRACT_NONE; - *(argv_min + 3) = 0; - *(argv_max + 3) = 1; - *(argv_def + 3) = 0; - *(argv_unit + 3) = XTRACT_NONE; - break; case XTRACT_PEAK_SPECTRUM: *argv_min = XTRACT_SR_LOWER_LIMIT / 2; *argv_max = XTRACT_SR_UPPER_LIMIT / 2; @@ -150,6 +132,43 @@ xtract_function_descriptor_t *xtract_make_descriptors(void){ *(argv_def + 1) = XTRACT_NONE; *(argv_unit + 1) = XTRACT_NONE; break; + /* argc = 4 */ + case XTRACT_SPECTRUM: + *argv_min = XTRACT_SR_LOWER_LIMIT / XTRACT_FFT_BANDS_MIN; + *argv_max = XTRACT_SR_UPPER_LIMIT / XTRACT_FFT_BANDS_MAX; + *argv_def = XTRACT_SR_DEFAULT / XTRACT_FFT_BANDS_DEF; + *argv_unit = XTRACT_HERTZ; + *(argv_min + 1) = 0; + *(argv_max + 1) = 3 ; + *(argv_def + 1) = 0; + *(argv_unit + 1) = XTRACT_NONE; + *(argv_min + 2) = 0; + *(argv_max + 2) = 1; + *(argv_def + 2) = 0; + *(argv_unit + 2) = XTRACT_NONE; + *(argv_min + 3) = 0; + *(argv_max + 3) = 1; + *(argv_def + 3) = 0; + *(argv_unit + 3) = XTRACT_NONE; + break; + case XTRACT_SUBBANDS: + *argv_min = XTRACT_ANY; + *argv_max = XTRACT_ANY; + *argv_def = XTRACT_MEAN; + *argv_unit = XTRACT_NONE; + *(argv_min + 1) = 1; + *(argv_max + 1) = 16384; + *(argv_def + 1) = 4; + *(argv_unit + 1) = XTRACT_NONE; + *(argv_min + 2) = 0; + *(argv_max + 2) = 32; + *(argv_def + 2) = 0; + *(argv_unit + 2) = XTRACT_NONE; + *(argv_min + 3) = 0; + *(argv_max + 3) = 1; + *(argv_def + 3) = 0; + *(argv_unit + 3) = XTRACT_NONE; + break; case XTRACT_BARK_COEFFICIENTS: /* BARK_COEFFICIENTS is special because argc = BARK_BANDS */ case XTRACT_WINDOWED: diff --git a/src/vector.c b/src/vector.c index ce74630..97a876b 100644 --- a/src/vector.c +++ b/src/vector.c @@ -573,4 +573,52 @@ int xtract_lpcc(const float *data, const int N, const void *argv, float *result) // return XTRACT_SUCCESS; //} +int xtract_subbands(const float *data, const int N, const void *argv, float *result){ + + int n, bw, xtract_func, nbands, scale, start, lower, *argi, rv; + + argi = (int *)argv; + + xtract_func = argi[0]; + nbands = argi[1]; + scale = argi[2]; + start = argi[3]; + + + if(scale == XTRACT_LINEAR_SUBBANDS) + bw = floorf((N - start) / nbands); + else + bw = start; + + lower = start; + + for(n = 0; n < nbands; n++){ + + /* Bounds sanity check */ + if(lower + bw >= N) + result[n] = 0.f + continue; + + rv = xtract[xtract_func](data+lower, bw, NULL, &result[n]); + + if(rv != XTRACT_SUCCESS) + return rv; + + switch(scale){ + case XTRACT_OCTAVE_SUBBANDS: + lower += bw; + bw = lower; + break; + case XTRACT_LINEAR_SUBBANDS: + lower += bw; + break; + } + + } + + return rv; + +} + + diff --git a/xtract/libxtract.h b/xtract/libxtract.h index 2fad148..44b3828 100644 --- a/xtract/libxtract.h +++ b/xtract/libxtract.h @@ -130,6 +130,7 @@ enum xtract_features_ { XTRACT_HARMONIC_SPECTRUM, XTRACT_LPC, XTRACT_LPCC, + XTRACT_SUBBANDS, /* Helper functions */ XTRACT_WINDOWED }; @@ -179,6 +180,12 @@ enum xtract_spectrum_ { XTRACT_LOG_POWER_SPECTRUM }; +/** \brief Subband scales */ +enum xtract_subband_scales_ { + XTRACT_OCTAVE_SUBBANDS, + XTRACT_LINEAR_SUBBANDS +}; + /** \brief Enumeration of data types*/ typedef enum type_ { XTRACT_FLOAT, diff --git a/xtract/xtract_vector.h b/xtract/xtract_vector.h index 07bf176..1d68080 100644 --- a/xtract/xtract_vector.h +++ b/xtract/xtract_vector.h @@ -158,8 +158,23 @@ int xtract_lpc(const float *data, const int N, const void *argv, float *result); */ int xtract_lpcc(const float *data, const int N, const void *argv, float *result); - - +/** \brief Extract subbands from a spectrum + * + * \param *data: a pointer to an array of size N containing N magnitude/power/log magnitude/log power coefficients. (e.g. the first half of the array pointed to by *result from xtract_spectrum(). + * \param N: the number of elements from the array pointed to by *data to be considered + * \param *argv: A pointer to an array containing four integers. The first represents the extraction function to applied to each subband e.g. XTRACT_SUM or XTRACT_MEAN, the second represents the number of subbands required, and the third represents the frequency scale to be used for the subband bounds as defined in the enumeration xtract_subband_scales_ (libxtract.h). The fourth integer represent the start point of the subbands as a location in the input array as pointed to by *data (e.g. a value of 5 would start the subband extraction at bin 5) + * \param *result: A pointer to an array containing the resultant subband values. The calling function is responsible for allocating and freeing memory for *result. xtract_subbands() assumes that at least argv[1] * sizeof(float) bytes have been allocated. If the requested nbands extends the subband range beyond N, then the remaining bands will be set to 0. If the array pointed to by *result has more than argv[1] elements, the superfluous elements will be unchanged. + * + * xtract_subbands() divides a spectrum into subbands and applies the function given by argv[0] to the values in each subband to give a 'reduced' representation of the spectrum as *result + * + * Specifying XTRACT_OCTAVE_SUBBANDS will extract subbands at each octave from the start bin until argv[1] is reached or N is reached + * Specifying XTRACT_LINEAR_SUBBANDS will extract argv[1] equal sized subbands between the start bin and N + * + * + * It is assumed that a sensible function will be given in argv[0], and for this function argv will always be NULL. Sensible values for argv[0] are XTRACT_MEAN and XTRACT_SUM, although something like XTRACT_IRREGULARITY_K might yield interesting results. + * + */ +int xtract_subbands(const float *data, const int N, const void *argv, float *result); /** @} */ #ifdef __cplusplus |