From 2e66bd6092fe93ca7fa953c4af9d0e16bbf69905 Mon Sep 17 00:00:00 2001 From: Jamie Bullock Date: Fri, 28 Dec 2007 19:34:51 +0000 Subject: - Added new helper functions: xtract_windowed() and xtract_features_from_subframes() - Added windowing functions (window.c) --- src/Makefile.am | 3 +- src/delta.c | 5 +- src/helper.c | 65 ++++++++++++++++ src/init.c | 102 ++++++++++++++++++------- src/libxtract.c | 8 +- src/scalar.c | 2 +- src/window.c | 182 ++++++++++++++++++++++++++++++++++++++++++++ src/xtract_window_private.h | 98 ++++++++++++++++++++++++ 8 files changed, 431 insertions(+), 34 deletions(-) create mode 100644 src/helper.c create mode 100644 src/window.c create mode 100644 src/xtract_window_private.h (limited to 'src') diff --git a/src/Makefile.am b/src/Makefile.am index bee5c4d..89154c5 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,6 +1,7 @@ MAINTAINERCLEANFILES = Makefile.in -SOURCES = libxtract.c descriptors.c scalar.c vector.c delta.c init.c fini.c +SOURCES = libxtract.c descriptors.c scalar.c vector.c delta.c init.c\ + window.c fini.c helper.c if BUILD_FFT FFT_DEFINE = -DXTRACT_FFT diff --git a/src/delta.c b/src/delta.c index 79250e2..8e9fcd0 100644 --- a/src/delta.c +++ b/src/delta.c @@ -32,8 +32,7 @@ int xtract_flux(const float *data, const int N, const void *argv , float *result int xtract_lnorm(const float *data, const int N, const void *argv , float *result){ - int feature, - n, + int n, type; float order, @@ -80,7 +79,7 @@ int xtract_decay_time(const float *data, const int N, const void *argv, float *r int xtract_difference_vector(const float *data, const int N, const void *argv, float *result){ - float *frame1, + const float *frame1, *frame2; int n; diff --git a/src/helper.c b/src/helper.c new file mode 100644 index 0000000..eceb290 --- /dev/null +++ b/src/helper.c @@ -0,0 +1,65 @@ +/* libxtract feature extraction library + * + * Copyright (C) 2006 Jamie Bullock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + + +/* helper.c: helper functions. */ + +#include "xtract/libxtract.h" + +int xtract_windowed(const float *data, const int N, const void *argv, float *result){ + + int n; + const float *window; + + n = N; + window = (const float *)argv; + + while(n--) + result[n] = data[n] * window[n]; + + return XTRACT_SUCCESS; + +} + +int xtract_features_from_subframes(const float *data, const int N, const int feature, const void *argv, float *result){ + + const float *frame1, + *frame2; + float *result1, + *result2; + + int n, + rv; + + n = N >> 1; + + frame1 = data; + frame2 = data + n; + result1 = result; + result2 = result + n; + + rv = xtract[feature](frame1, n, argv, result1); + + if(rv == XTRACT_SUCCESS) + rv = xtract[feature](frame2, n, argv, result2); + + return rv; + +} diff --git a/src/init.c b/src/init.c index 37be14c..6112e73 100644 --- a/src/init.c +++ b/src/init.c @@ -18,7 +18,7 @@ * USA. */ -/* init.c: defines functions that extract a feature as a single value from an input vector */ +/* init.c: defines initialisation and free functions. Also contains library constructor routine. */ #ifdef HAVE_CONFIG_H # include @@ -28,6 +28,7 @@ #include #include "xtract/libxtract.h" +#include "xtract_window_private.h" #define DEFINE_GLOBALS #include "xtract_globals_private.h" @@ -43,7 +44,7 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq int n, i, k, *fft_peak, M, next_peak; float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val, - freq_bw_mel, *mel_peak, *height_norm, *lin_peak; + freq_bw_mel, *mel_peak, *height_norm, *lin_peak; mel_peak = height_norm = lin_peak = NULL; fft_peak = NULL; @@ -60,9 +61,9 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq height_norm = (float *)malloc(freq_bands * sizeof(float)); if(mel_peak == NULL || height_norm == NULL || - lin_peak == NULL || fft_peak == NULL) - return XTRACT_MALLOC_FAILED; - + lin_peak == NULL || fft_peak == NULL) + return XTRACT_MALLOC_FAILED; + M = N >> 1; mel_peak[0] = mel_freq_min; @@ -91,41 +92,41 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq } i = 0; - + for(n = 0; n < freq_bands; n++){ - - // calculate the rise increment + + // calculate the rise increment if(n==0) inc = height_norm[n] / fft_peak[n]; else inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]); val = 0; - - // zero the start of the array - for(k = 0; k < i; k++) - fft_tables[n][k] = 0.f; - - // fill in the rise + + // zero the start of the array + for(k = 0; k < i; k++) + fft_tables[n][k] = 0.f; + + // fill in the rise for(; i <= fft_peak[n]; i++){ fft_tables[n][i] = val; val += inc; } - + // calculate the fall increment inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]); - + val = 0; - next_peak = fft_peak[n + 1]; - - // reverse fill the 'fall' + next_peak = fft_peak[n + 1]; + + // reverse fill the 'fall' for(i = next_peak; i > fft_peak[n]; i--){ fft_tables[n][i] = val; val += inc; } - // zero the rest of the array - for(k = next_peak + 1; k < N; k++) - fft_tables[n][k] = 0.f; + // zero the rest of the array + for(k = next_peak + 1; k < N; k++) + fft_tables[n][k] = 0.f; } @@ -145,9 +146,9 @@ int xtract_init_fft(int N, int feature_name){ float *input, *output; int optimisation; - + input = output = NULL; - + fprintf(stderr, "Optimisation level: %d\n", XTRACT_FFT_OPTIMISATION_LEVEL); if(XTRACT_FFT_OPTIMISATION_LEVEL == 0) @@ -209,14 +210,63 @@ int xtract_init_bark(int N, float sr, int *band_limits){ 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 bands = XTRACT_BARK_BANDS; - + while(bands--) band_limits[bands] = edges[bands] / sr * N; - /*FIX shohuld use rounding, but couldn't get it to work */ + /*FIX shohuld use rounding, but couldn't get it to work */ return XTRACT_SUCCESS; } +float *xtract_init_window(const int N, const int type){ + + float *window; + + window = malloc(N * sizeof(float)); + + switch (type) { + case XTRACT_GAUSS: + gauss(window, N, 0.4); + break; + case XTRACT_HAMMING: + hamming(window, N); + break; + case XTRACT_HANN: + hann(window, N); + break; + case XTRACT_BARTLETT: + bartlett(window, N); + break; + case XTRACT_TRIANGULAR: + triangular(window, N); + break; + case XTRACT_BARTLETT_HANN: + bartlett_hann(window, N); + break; + case XTRACT_BLACKMAN: + blackman(window, N); + break; + case XTRACT_KAISER: + kaiser(window, N, 3 * PI); + break; + case XTRACT_BLACKMAN_HARRIS: + blackman_harris(window, N); + break; + default: + hann(window, N); + break; + } + + return window; + +} + +void xtract_free_window(float *window){ + + free(window); + +} + #ifdef __GNUC__ __attribute__((constructor)) void init() #else diff --git a/src/libxtract.c b/src/libxtract.c index cf0dd1a..c46883e 100644 --- a/src/libxtract.c +++ b/src/libxtract.c @@ -64,13 +64,13 @@ int(*xtract[])(const float *, const int, const void *, float *) = { xtract_hps, xtract_f0, xtract_failsafe_f0, -/* xtract_delta.h */ + /* xtract_delta.h */ xtract_lnorm, xtract_flux, xtract_attack_time, xtract_decay_time, xtract_difference_vector, -/* xtract_vector.h */ + /* xtract_vector.h */ xtract_autocorrelation, xtract_amdf, xtract_asdf, @@ -82,6 +82,8 @@ int(*xtract[])(const float *, const int, const void *, float *) = { xtract_dct, xtract_harmonic_spectrum, xtract_lpc, - xtract_lpcc + xtract_lpcc, + /* xtract_helper.h */ + xtract_windowed }; diff --git a/src/scalar.c b/src/scalar.c index b573102..6c29f91 100644 --- a/src/scalar.c +++ b/src/scalar.c @@ -19,7 +19,7 @@ */ -/* xtract_scalar.c: defines functions that extract a feature as a single value from an input vector */ +/* scalar.c: defines functions that extract a feature as a single value from an input vector */ #include "xtract/libxtract.h" #include "xtract_macros_private.h" diff --git a/src/window.c b/src/window.c new file mode 100644 index 0000000..f2ceecc --- /dev/null +++ b/src/window.c @@ -0,0 +1,182 @@ +/* libxtract feature extraction library + * + * Copyright (C) 2006 Jamie Bullock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +/* window.c: defines window generation functions (formulae courtesy of Wikipedia (http://en.wikipedia.org/wiki/Window_function) */ + +#include + +#include "xtract_window_private.h" + +void gauss(float *window, const int N, const float sd){ + + int n; + const float M = N - 1; + float num, + den, + exponent; + + for (n = 0; n < N; n++) { + + num = n - M / 2.f; + den = sd * M / 2.f; + + exponent = -0.5 * powf(num / den, 2); + + window[n] = exp(exponent); + + } +} + +void hamming(float *window, const int N){ + + int n; + const float M = N - 1; + + for (n = 0; n < N; n++) + window[n] = 0.53836 - (0.46164 * cosf(2.0 * PI * (float)n / M)); + +} + +void hann(float *window, const int N){ + + int n; + const float M = N - 1; + + for (n = 0; n < N; n++) + window[n] = 0.5 * (1.0 - cosf(2.0 * PI * (float)n / M)); + +} + +void bartlett(float *window, const int N){ + + int n; + const float M = N - 1; + + for (n = 0; n < N; n++) + window[n] = 2.f / M * (M / 2.f - fabsf(n - M / 2.f)); + +} + +void triangular(float *window, const int N){ + + int n; + const float M = N - 1; + + for (n = 0; n < N; n++) + window[n] = 2.f / N * (N / 2.f - fabsf(n - M / 2.f)); +} + +void bartlett_hann(float *window, const int N){ + + int n; + const float M = N - 1, + a0 = 0.62, + a1 = 0.5, + a2 = 0.38; + float term1 = 0.f, + term2 = 0.f; + + for (n = 0; n < N; n++){ + + term1 = a1 * fabsf(n / M - 0.5); + term2 = a2 * cosf(2.0 * PI * (float)n / M); + + window[n] = a0 - term1 - term2; + } +} + +void blackman(float *window, const int N){ + + int n; + const float M = N - 1, + a0 = 0.42, + a1 = 0.5, + a2 = 0.08; + float term1 = 0.f, + term2 = 0.f; + + for (n = 0; n < N; n++) { + + term1 = a1 * cosf(2.0 * PI * (float)n / M); + term2 = a2 * cosf(4.0 * PI * (float)n / M); + + window[n] = a0 - term1 + term2; + } +} + +#define BIZ_EPSILON 1E-21 // Max error acceptable + +/* Based on code from mplayer window.c, and somewhat beyond me */ +float besselI0(float x){ + + float temp; + float sum = 1.0; + float u = 1.0; + float halfx = x/2.0; + int n = 1; + + do { + + temp = halfx/(float)n; + u *=temp * temp; + sum += u; + n++; + + } while (u >= BIZ_EPSILON * sum); + + return(sum); + +} + +void kaiser(float *window, const int N, const float alpha){ + + int n; + const float M = N - 1; + float num; + + for (n = 0; n < N; n++) { + + num = besselI0(alpha * sqrtf(1.0 - powf((2.0 * n / M - 1), 2))); + window[n] = num / besselI0(alpha); + + } +} + +void blackman_harris(float *window, const int N){ + + int n; + const float M = N - 1, + a0 = 0.35875, + a1 = 0.48829, + a2 = 0.14128, + a3 = 0.01168; + float term1 = 0.f, + term2 = 0.f, + term3 = 0.f; + + for (n = 0; n < N; n++) { + + term1 = a1 * cosf(2.0 * PI * n / M); + term2 = a2 * cosf(4.0 * PI * n / M); + term3 = a3 * cosf(6.0 * PI * n / M); + + window[n] = a0 - term1 + term2 - term3; + } +} diff --git a/src/xtract_window_private.h b/src/xtract_window_private.h new file mode 100644 index 0000000..661b92f --- /dev/null +++ b/src/xtract_window_private.h @@ -0,0 +1,98 @@ +/* libxtract feature extraction library + * + * Copyright (C) 2006 Jamie Bullock + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + */ + +/* xtract_window_private.h: declares window generation functions */ + +#define PI 3.1415926535897931 + +/** \brief generate a Gaussian window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * \param sd the standard deviation of the "distribution" represented by the Gaussian curve. The higher the value of sd, the wider the curve. Generally sd <= 0.5 + * + */ +void gauss(float *window, const int N, const float sd); + +/** \brief generate a Hamming window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void hamming(float *window, const int N); + +/** \brief generate a Hann window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void hann(float *window, const int N); + +/** \brief generate a Bartlett window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void bartlett(float *window, const int N); + +/** \brief generate a Triangular window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void triangular(float *window, const int N); + +/** \brief generate a Bartlett-Hann window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void bartlett_hann(float *window, const int N); + +/** \brief generate a Blackman window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void blackman(float *window, const int N); + +/** \brief generate a Kaiser window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * \param alpha The larger the value of |alpha|, the narrower the window becomes + * + */ +void kaiser(float *window, const int N, const float alpha); + +/** \brief generate a Blackman-Harris window + * + * \param *window a pointer to an array to contain the window data + * \param N the number of elements in the array pointed to by *window + * + */ +void blackman_harris(float *window, const int N); + -- cgit v1.2.3