diff options
author | Jamie Bullock <jamie@jamiebullock.com> | 2013-01-07 16:27:15 +0000 |
---|---|---|
committer | Jamie Bullock <jamie@jamiebullock.com> | 2013-01-07 16:39:29 +0000 |
commit | 144e7f8668166ee1779ad304cc5ac94d8e525529 (patch) | |
tree | 089b2bbbcf15ee8bdde390a4d270e4812e7e2228 /src/vector.c | |
parent | 0f46938156dedf13032bdb1fc914a63d46bae558 (diff) | |
download | LibXtract-144e7f8668166ee1779ad304cc5ac94d8e525529.tar.gz LibXtract-144e7f8668166ee1779ad304cc5ac94d8e525529.tar.bz2 LibXtract-144e7f8668166ee1779ad304cc5ac94d8e525529.zip |
added Ooura implementation to repository
Diffstat (limited to 'src/vector.c')
-rw-r--r-- | src/vector.c | 467 |
1 files changed, 249 insertions, 218 deletions
diff --git a/src/vector.c b/src/vector.c index 9c29762..73e437f 100644 --- a/src/vector.c +++ b/src/vector.c @@ -1,5 +1,5 @@ /* libxtract feature extraction library - * + * * Copyright (C) 2006 Jamie Bullock * * This program is free software; you can redistribute it and/or modify @@ -14,7 +14,7 @@ * * 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, + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ @@ -25,16 +25,19 @@ #include <string.h> #include <stdlib.h> +#include "fftsg.h" + #include "xtract/libxtract.h" #include "xtract_macros_private.h" #ifndef roundf - float roundf(float f){ - if (f - (int)f >= 0.5) - return (float)((int)f + 1); - else - return (float)((int)f); - } +float roundf(float f) +{ + if (f - (int)f >= 0.5) + return (float)((int)f + 1); + else + return (float)((int)f); +} #endif #ifndef powf @@ -53,185 +56,208 @@ #define fabsf fabs #endif -#ifdef XTRACT_FFT - -#include <fftw3.h> #include "xtract_globals_private.h" #include "xtract_macros_private.h" -int xtract_spectrum(const float *data, const int N, const void *argv, float *result){ - - float *input, *rfft, q, temp, max, NxN; - size_t bytes; - int n, - m, - M, - vector, - withDC, - argc, - normalise; - - vector = argc = withDC = normalise = 0; - - M = N >> 1; - NxN = XTRACT_SQ(N); - - rfft = (float *)fftwf_malloc(N * sizeof(float)); - input = (float *)malloc(bytes = N * sizeof(float)); - input = memcpy(input, data, bytes); +int xtract_spectrum(const float *data, const int N, const void *argv, float *result) +{ + + int vector = 0; + int withDC = 0; + int normalise = 0; + float q = 0.f; + float temp = 0.f; + float max = 0.f; + float NxN = XTRACT_SQ(N); + float *marker = NULL; + size_t bytes = N * sizeof(double); + double *rfft = NULL; + unsigned int n = 0; + unsigned int m = 0; + unsigned int nx2 = 0; + unsigned int M = N >> 1; + + rfft = (double *)malloc(bytes); + //memcpy(rfft, data, bytes); + + for(n = 0; n < N; ++n){ + rfft[n] = (double)data[n]; + } q = *(float *)argv; vector = (int)*((float *)argv+1); withDC = (int)*((float *)argv+2); normalise = (int)*((float *)argv+3); - temp = 0.f; - max = 0.f; - XTRACT_CHECK_q; - if(fft_plans.spectrum_plan == NULL){ - fprintf(stderr, - "libxtract: Error: xtract_spectrum() has uninitialised plan\n"); + if(!ooura_data_spectrum.initialised) + { + fprintf(stderr, + "libxtract: error: xtract_spectrum() failed, " + "fft data unitialised.\n"); return XTRACT_NO_RESULT; } - fftwf_execute_r2r(fft_plans.spectrum_plan, input, rfft); + /* ooura is in-place + * the output format seems to be + * a[0] - DC, a[1] - nyquist, a[2...N-1] - remaining bins + */ + rdft(N, 1, rfft, ooura_data_spectrum.ooura_ip, + ooura_data_spectrum.ooura_w); - switch(vector){ + switch(vector) + { case XTRACT_LOG_MAGNITUDE_SPECTRUM: - for(n = 0, m = 0; m < M; ++n, ++m){ - if(!withDC && n == 0){ - ++n; - } - if ((temp = XTRACT_SQ(rfft[n]) + - XTRACT_SQ(rfft[N - n])) > XTRACT_LOG_LIMIT) - temp = logf(sqrtf(temp) / (float)N); - else - temp = XTRACT_LOG_LIMIT_DB; - - result[m] = - /* Scaling */ - (temp + XTRACT_DB_SCALE_OFFSET) / - XTRACT_DB_SCALE_OFFSET; - - XTRACT_SET_FREQUENCY; - XTRACT_GET_MAX; + for(n = 0, m = 0; m < M; ++n, ++m) + { + if(!withDC && n == 0) + { + continue; } - break; - - case XTRACT_POWER_SPECTRUM: - for(n = 0, m = 0; m < M; ++n, ++m){ - if(!withDC && n == 0){ - ++n; - } - result[m] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN; - XTRACT_SET_FREQUENCY; - XTRACT_GET_MAX; + nx2 = n * 2; + temp = XTRACT_SQ(rfft[nx2]) + XTRACT_SQ(rfft[nx2+1]); + if (temp > XTRACT_LOG_LIMIT) + { + temp = logf(sqrtf(temp) / (float)N); } - break; - - case XTRACT_LOG_POWER_SPECTRUM: - for(n = 0, m = 0; m < M; ++n, ++m){ - if(!withDC && n == 0){ - ++n; - } - if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) > - XTRACT_LOG_LIMIT) - temp = logf(temp / NxN); - else - temp = XTRACT_LOG_LIMIT_DB; - - result[m] = (temp + XTRACT_DB_SCALE_OFFSET) / - XTRACT_DB_SCALE_OFFSET; - XTRACT_SET_FREQUENCY; - XTRACT_GET_MAX; + else + { + temp = XTRACT_LOG_LIMIT_DB; } - break; + result[m] = + /* Scaling */ + (temp + XTRACT_DB_SCALE_OFFSET) / + XTRACT_DB_SCALE_OFFSET; - default: - /* MAGNITUDE_SPECTRUM */ - for(n = 0, m = 0; m < M; ++n, ++m){ - if(!withDC && n == 0){ - ++n; - } - result[m] = sqrtf(XTRACT_SQ(rfft[n]) + - XTRACT_SQ(rfft[N - n])) / (float)N; - XTRACT_SET_FREQUENCY; - XTRACT_GET_MAX; + XTRACT_SET_FREQUENCY; + XTRACT_GET_MAX; + } + break; + + case XTRACT_POWER_SPECTRUM: + for(n = 0, m = 0; m < M; ++n, ++m) + { + if(!withDC && n == 0) + { + ++n; } - break; + result[m] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN; + XTRACT_SET_FREQUENCY; + XTRACT_GET_MAX; + } + break; + + case XTRACT_LOG_POWER_SPECTRUM: + for(n = 0, m = 0; m < M; ++n, ++m) + { + if(!withDC && n == 0) + { + ++n; + } + if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) > + XTRACT_LOG_LIMIT) + temp = logf(temp / NxN); + else + temp = XTRACT_LOG_LIMIT_DB; + + result[m] = (temp + XTRACT_DB_SCALE_OFFSET) / + XTRACT_DB_SCALE_OFFSET; + XTRACT_SET_FREQUENCY; + XTRACT_GET_MAX; + } + break; + + default: + /* MAGNITUDE_SPECTRUM */ + for(n = 0, m = 0; m < M; ++n, ++m) + { + marker = &result[m]; + + if(n==0 && !withDC) /* discard DC and keep Nyquist */ + { + ++n; + marker = &result[M-1]; + } + if(n==1 && withDC) /* discard Nyquist */ + { + ++n; + } + + *marker = (float)(sqrt(XTRACT_SQ(rfft[n*2]) + + XTRACT_SQ(rfft[n*2+1])) / (double)N); + XTRACT_SET_FREQUENCY; + XTRACT_GET_MAX; + + } + break; } - if(normalise){ + if(normalise) + { for(n = 0; n < M; n++) result[n] /= max; } - fftwf_free(rfft); - free(input); + free(rfft); return XTRACT_SUCCESS; } -int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){ +int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result) +{ - float *freq, *time; - int n, M; - //fftwf_plan plan; + double *rfft = NULL; + int n = 0; + int M = 0; M = N << 1; - freq = (float *)fftwf_malloc(M * sizeof(float)); /* Zero pad the input vector */ - time = (float *)calloc(M, sizeof(float)); - time = memcpy(time, data, N * sizeof(float)); - - fftwf_execute_r2r(fft_plans.autocorrelation_fft_plan_1, time, freq); - //plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE); + rfft = (double *)calloc(M, sizeof(double)); + memcpy(rfft, data, N * sizeof(float)); - //fftwf_execute(plan); + rdft(M, 1, rfft, ooura_data_autocorrelation_fft.ooura_ip, + ooura_data_autocorrelation_fft.ooura_w); - for(n = 1; n < N; n++){ - freq[n] = XTRACT_SQ(freq[n]) + XTRACT_SQ(freq[M - n]); - freq[M - n] = 0.f; + for(n = 2; n < M; n++) + { + rfft[n*2] = XTRACT_SQ(rfft[n*2]) + XTRACT_SQ(rfft[n*2+1]); + rfft[n*2+1] = 0.f; } - freq[0] = XTRACT_SQ(freq[0]); - freq[N] = XTRACT_SQ(freq[N]); - - //plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE); - - //fftwf_execute(plan); + rfft[0] = XTRACT_SQ(rfft[0]); + rfft[1] = XTRACT_SQ(rfft[1]); - fftwf_execute_r2r(fft_plans.autocorrelation_fft_plan_2, freq, time); + rdft(M, -1, rfft, ooura_data_autocorrelation_fft.ooura_ip, + ooura_data_autocorrelation_fft.ooura_w); /* Normalisation factor */ M = M * N; for(n = 0; n < N; n++) - result[n] = time[n] / (float)M; - /* result[n] = time[n+1] / (float)M; */ + result[n] = rfft[n] / (float)M; - //fftwf_destroy_plan(plan); - fftwf_free(freq); - free(time); + free(rfft); return XTRACT_SUCCESS; } -int xtract_mfcc(const float *data, const int N, const void *argv, float *result){ +int xtract_mfcc(const float *data, const int N, const void *argv, float *result) +{ xtract_mel_filter *f; int n, filter; f = (xtract_mel_filter *)argv; - for(filter = 0; filter < f->n_filters; filter++){ + for(filter = 0; filter < f->n_filters; filter++) + { result[filter] = 0.f; - for(n = 0; n < N; n++){ + for(n = 0; n < N; n++) + { result[filter] += data[n] * f->filters[filter][n]; } result[filter] = logf(result[filter] < XTRACT_LOG_LIMIT ? XTRACT_LOG_LIMIT : result[filter]); @@ -242,53 +268,25 @@ int xtract_mfcc(const float *data, const int N, const void *argv, float *result) return XTRACT_SUCCESS; } -int xtract_dct(const float *data, const int N, const void *argv, float *result){ +int xtract_dct(const float *data, const int N, const void *argv, float *result) +{ - //fftwf_plan plan; + int n; + int m; + float *temp = calloc(N, sizeof(float)); - //plan = - // fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE); - - fftwf_execute_r2r(fft_plans.dct_plan, (float *)data, result); - //fftwf_execute(plan); - //fftwf_destroy_plan(plan); - - return XTRACT_SUCCESS; -} - -#else - -int xtract_spectrum(const float *data, const int N, const void *argv, float *result){ - - XTRACT_NEEDS_FFTW; - return XTRACT_NO_RESULT; - -} - -int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){ - - XTRACT_NEEDS_FFTW; - return XTRACT_NO_RESULT; - -} - -int xtract_mfcc(const float *data, const int N, const void *argv, float *result){ - - XTRACT_NEEDS_FFTW; - return XTRACT_NO_RESULT; - -} - -int xtract_dct(const float *data, const int N, const void *argv, float *result){ - - XTRACT_NEEDS_FFTW; - return XTRACT_NO_RESULT; + for (n = 0; n < N; ++n) + { + for(m = 1; m <= N; ++m) { + temp[n] += data[m - 1] * cos(M_PI * (n / (float)N) * (m - 0.5)); + } + } + return XTRACT_SUCCESS; } -#endif - -int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){ +int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result) +{ /* Naive time domain implementation */ @@ -296,9 +294,11 @@ int xtract_autocorrelation(const float *data, const int N, const void *argv, flo float corr; - while(n--){ + while(n--) + { corr = 0; - for(i = 0; i < N - n; i++){ + for(i = 0; i < N - n; i++) + { corr += data[i] * data[i + n]; } result[n] = corr / N; @@ -307,15 +307,18 @@ int xtract_autocorrelation(const float *data, const int N, const void *argv, flo return XTRACT_SUCCESS; } -int xtract_amdf(const float *data, const int N, const void *argv, float *result){ +int xtract_amdf(const float *data, const int N, const void *argv, float *result) +{ int n = N, i; float md, temp; - while(n--){ + while(n--) + { md = 0.f; - for(i = 0; i < N - n; i++){ + for(i = 0; i < N - n; i++) + { temp = data[i] - data[i + n]; temp = (temp < 0 ? -temp : temp); md += temp; @@ -326,15 +329,18 @@ int xtract_amdf(const float *data, const int N, const void *argv, float *result) return XTRACT_SUCCESS; } -int xtract_asdf(const float *data, const int N, const void *argv, float *result){ +int xtract_asdf(const float *data, const int N, const void *argv, float *result) +{ int n = N, i; float sd; - while(n--){ + while(n--) + { sd = 0.f; - for(i = 0; i < N - n; i++){ + for(i = 0; i < N - n; i++) + { /*sd = 1;*/ sd += XTRACT_SQ(data[i] - data[i + n]); } @@ -344,13 +350,15 @@ int xtract_asdf(const float *data, const int N, const void *argv, float *result) return XTRACT_SUCCESS; } -int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){ +int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result) +{ int *limits, band, n; limits = (int *)argv; - for(band = 0; band < XTRACT_BARK_BANDS - 1; band++){ + for(band = 0; band < XTRACT_BARK_BANDS - 1; band++) + { result[band] = 0.f; for(n = limits[band]; n < limits[band + 1]; n++) result[band] += data[n]; @@ -359,7 +367,8 @@ int xtract_bark_coefficients(const float *data, const int N, const void *argv, f return XTRACT_SUCCESS; } -int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){ +int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result) +{ float threshold, max, y, y2, y3, p, q, *input = NULL; size_t bytes; @@ -367,14 +376,16 @@ int xtract_peak_spectrum(const float *data, const int N, const void *argv, float threshold = max = y = y2 = y3 = p = q = 0.f; - if(argv != NULL){ + if(argv != NULL) + { q = ((float *)argv)[0]; threshold = ((float *)argv)[1]; } else rv = XTRACT_BAD_ARGV; - if(threshold < 0 || threshold > 100){ + if(threshold < 0 || threshold > 100) + { threshold = 0; rv = XTRACT_BAD_ARGV; } @@ -398,32 +409,38 @@ int xtract_peak_spectrum(const float *data, const int N, const void *argv, float result[0] = 0; result[N] = 0; - for(n = 1; n < N; n++){ - if(input[n] >= threshold){ - if(input[n] > input[n - 1] && n + 1 < N && input[n] > input[n + 1]){ - result[N + n] = q * (n + (p = .5 * ((y = input[n-1]) - - (y3 = input[n+1])) / (input[n - 1] - 2 * - (y2 = input[n]) + input[n + 1]))); + for(n = 1; n < N; n++) + { + if(input[n] >= threshold) + { + if(input[n] > input[n - 1] && n + 1 < N && input[n] > input[n + 1]) + { + result[N + n] = q * (n + (p = .5 * ((y = input[n-1]) - + (y3 = input[n+1])) / (input[n - 1] - 2 * + (y2 = input[n]) + input[n + 1]))); result[n] = y2 - .25 * (y - y3) * p; } - else{ + else + { result[n] = 0; result[N + n] = 0; } } - else{ + else + { result[n] = 0; result[N + n] = 0; } - } + } free(input); return (rv ? rv : XTRACT_SUCCESS); } -int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){ +int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result) +{ - int n = (N >> 1), M = n; + int n = (N >> 1), M = n; const float *freqs, *amps; float f0, threshold, ratio, nearest, distance; @@ -435,14 +452,17 @@ int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, f ratio = nearest = distance = 0.f; - while(n--){ - if(freqs[n]){ + while(n--) + { + if(freqs[n]) + { ratio = freqs[n] / f0; nearest = roundf(ratio); distance = fabs(nearest - ratio); if(distance > threshold) result[n] = result[M + n] = 0.f; - else { + else + { result[n] = amps[n]; result[M + n] = freqs[n]; } @@ -453,14 +473,15 @@ int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, f return XTRACT_SUCCESS; } -int xtract_lpc(const float *data, const int N, const void *argv, float *result){ +int xtract_lpc(const float *data, const int N, const void *argv, float *result) +{ int i, j, k, M, L; - float r = 0.f, + float r = 0.f, error = 0.f; float *ref = NULL, - *lpc = NULL ; + *lpc = NULL ; error = data[0]; k = N; /* The length of *data */ @@ -469,24 +490,27 @@ int xtract_lpc(const float *data, const int N, const void *argv, float *result){ ref = result; lpc = result+L; - if(error == 0.0){ + if(error == 0.0) + { memset(result, 0, M * sizeof(float)); return XTRACT_NO_RESULT; } memset(result, 0, M * sizeof(float)); - for (i = 0; i < L; i++) { + for (i = 0; i < L; i++) + { /* Sum up this iteration's reflection coefficient. */ r = -data[i + 1]; - for (j = 0; j < i; j++) + for (j = 0; j < i; j++) r -= lpc[j] * data[i - j]; ref[i] = r /= error; /* Update LPC coefficients and total error. */ lpc[i] = r; - for (j = 0; j < i / 2; j++) { + for (j = 0; j < i / 2; j++) + { float tmp = lpc[j]; lpc[j] = r * lpc[i - 1 - j]; lpc[i - 1 - j] += r * tmp; @@ -499,7 +523,8 @@ int xtract_lpc(const float *data, const int N, const void *argv, float *result){ return XTRACT_SUCCESS; } -int xtract_lpcc(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) +{ /* Given N lpc coefficients extract an LPC cepstrum of size argv[0] */ /* Based on an an algorithm by rabiner and Juang */ @@ -507,7 +532,7 @@ int xtract_lpcc(const float *data, const int N, const void *argv, float *result) int n, k; float sum; int order = N - 1; /* Eventually change this to Q = 3/2 p as suggested in Rabiner */ - int cep_length; + int cep_length; if(argv == NULL) cep_length = N - 1; /* FIX: if we're going to have default values, they should come from the descriptor */ @@ -517,7 +542,8 @@ int xtract_lpcc(const float *data, const int N, const void *argv, float *result) memset(result, 0, cep_length * sizeof(float)); - for (n = 1; n <= order && n <= cep_length; n++){ + for (n = 1; n <= order && n <= cep_length; n++) + { sum = 0.f; for (k = 1; k < n; k++) sum += k * result[k-1] * data[n - k]; @@ -525,7 +551,8 @@ int xtract_lpcc(const float *data, const int N, const void *argv, float *result) } /* be wary of these interpolated values */ - for(n = order + 1; n <= cep_length; n++){ + for(n = order + 1; n <= cep_length; n++) + { sum = 0.f; for (k = n - (order - 1); k < n; k++) sum += k * result[k-1] * data[n - k]; @@ -539,7 +566,8 @@ 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 xtract_subbands(const float *data, const int N, const void *argv, float *result) +{ int n, bw, xtract_func, nbands, scale, start, lower, *argi, rv; @@ -558,10 +586,12 @@ int xtract_subbands(const float *data, const int N, const void *argv, float *res lower = start; rv = XTRACT_SUCCESS; - for(n = 0; n < nbands; n++){ + for(n = 0; n < nbands; n++) + { /* Bounds sanity check */ - if(lower >= N || lower + bw >= N){ + if(lower >= N || lower + bw >= N) + { // printf("n: %d\n", n); result[n] = 0.f; continue; @@ -572,14 +602,15 @@ int xtract_subbands(const float *data, const int N, const void *argv, float *res if(rv != XTRACT_SUCCESS) return rv; - switch(scale){ - case XTRACT_OCTAVE_SUBBANDS: - lower += bw; - bw = lower; - break; - case XTRACT_LINEAR_SUBBANDS: - lower += bw; - break; + switch(scale) + { + case XTRACT_OCTAVE_SUBBANDS: + lower += bw; + bw = lower; + break; + case XTRACT_LINEAR_SUBBANDS: + lower += bw; + break; } } |