aboutsummaryrefslogtreecommitdiff
path: root/src/init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/init.c')
-rw-r--r--src/init.c310
1 files changed, 165 insertions, 145 deletions
diff --git a/src/init.c b/src/init.c
index 0fb272b..7b932da 100644
--- a/src/init.c
+++ b/src/init.c
@@ -1,21 +1,24 @@
-/* libxtract feature extraction library
- *
- * Copyright (C) 2006 Jamie Bullock
+/*
+ * Copyright (C) 2012 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.
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
*
- * 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.
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
*
- * 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.
*/
/* init.c: defines initialisation and free functions. Also contains library constructor routine. */
@@ -26,41 +29,38 @@
#include <math.h>
#include <stdlib.h>
+#include <stdio.h>
+
+#include "fftsg.h"
#include "xtract/libxtract.h"
#include "xtract_window_private.h"
#define DEFINE_GLOBALS
#include "xtract_globals_private.h"
-#ifdef XTRACT_FFT
-#include <fftw3.h>
-#ifndef XTRACT_FFT_OPTIMISATION_LEVEL
-/* This should never happen */
-#define XTRACT_FFT_OPTIMISATION_LEVEL 1
-#endif
-
-int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables){
+int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables)
+{
- int n, i, k, *fft_peak, M, next_peak;
- float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
+ 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;
mel_peak = height_norm = lin_peak = NULL;
fft_peak = NULL;
- norm = 1;
+ norm = 1;
mel_freq_max = 1127 * log(1 + freq_max / 700);
mel_freq_min = 1127 * log(1 + freq_min / 700);
freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
- mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
+ mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
/* +2 for zeros at start and end */
lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
height_norm = (float *)malloc(freq_bands * sizeof(float));
- if(mel_peak == NULL || height_norm == NULL ||
+ if(mel_peak == NULL || height_norm == NULL ||
lin_peak == NULL || fft_peak == NULL)
return XTRACT_MALLOC_FAILED;
@@ -71,20 +71,24 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
fft_peak[0] = lin_peak[0] / nyquist * M;
- for (n = 1; n < freq_bands + 2; n++){
- //roll out peak locations - mel, linear and linear on fft window scale
+ for (n = 1; n < freq_bands + 2; n++)
+ {
+ //roll out peak locations - mel, linear and linear on fft window scale
mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
fft_peak[n] = lin_peak[n] / nyquist * M;
}
- for (n = 0; n < freq_bands; n++){
+ for (n = 0; n < freq_bands; n++)
+ {
//roll out normalised gain of each peak
- if (style == XTRACT_EQUAL_GAIN){
- height = 1;
+ if (style == XTRACT_EQUAL_GAIN)
+ {
+ height = 1;
norm_fact = norm;
}
- else{
+ else
+ {
height = 2 / (lin_peak[n + 2] - lin_peak[n]);
norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
}
@@ -93,21 +97,23 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
i = 0;
- for(n = 0; n < freq_bands; n++){
+ for(n = 0; n < freq_bands; n++)
+ {
// 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;
+ val = 0;
// 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++){
+ for(; i <= fft_peak[n]; i++)
+ {
fft_tables[n][i] = val;
val += inc;
}
@@ -118,8 +124,9 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
val = 0;
next_peak = fft_peak[n + 1];
- // reverse fill the 'fall'
- for(i = next_peak; i > fft_peak[n]; i--){
+ // reverse fill the 'fall'
+ for(i = next_peak; i > fft_peak[n]; i--)
+ {
fft_tables[n][i] = val;
val += inc;
}
@@ -131,7 +138,10 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
/* Initialise the fft_plan for the DCT */
+ /*
+ * Ooura doesn't support non power-of-two DCT
xtract_init_fft(freq_bands, XTRACT_MFCC);
+ */
free(mel_peak);
free(lin_peak);
@@ -142,82 +152,95 @@ int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq
}
-int xtract_init_fft(int N, int feature_name){
+void xtract_init_ooura(xtract_ooura_data *ooura_data, unsigned int N)
+{
+ ooura_data->ooura_ip = (int *)calloc((2 + sqrt(N)), sizeof(int));
+ ooura_data->ooura_w = (double *)calloc((N - 1), sizeof(double));
+ ooura_data->initialised = true;
+}
- float *input, *output;
- int optimisation;
+void xtract_free_ooura(xtract_ooura_data *ooura_data)
+{
+ free(ooura_data->ooura_ip);
+ free(ooura_data->ooura_w);
+ ooura_data->ooura_ip = NULL;
+ ooura_data->ooura_w = NULL;
+ ooura_data->initialised = false;
+}
- input = output = NULL;
+int xtract_init_fft(int N, int feature_name)
+{
- //fprintf(stderr, "Optimisation level: %d\n", XTRACT_FFT_OPTIMISATION_LEVEL);
+ int M = N >> 1;
- if(XTRACT_FFT_OPTIMISATION_LEVEL == 0)
- optimisation = FFTW_ESTIMATE;
- else if(XTRACT_FFT_OPTIMISATION_LEVEL == 1)
- optimisation = FFTW_MEASURE;
- else if(XTRACT_FFT_OPTIMISATION_LEVEL == 2)
- optimisation = FFTW_PATIENT;
- else
- optimisation = FFTW_MEASURE; /* The default */
+ if(!xtract_is_poweroftwo(N))
+ {
+ fprintf(stderr,
+ "libxtract: error: only power-of-two FFT sizes are supported.\n");
+ exit(EXIT_FAILURE);
+ }
if(feature_name == XTRACT_AUTOCORRELATION_FFT)
- N <<= 1;
-
- input = malloc(N * sizeof(float));
- output = malloc(N * sizeof(float));
-
- switch(feature_name){
- case XTRACT_SPECTRUM:
- if(fft_plans.spectrum_plan != NULL)
- fftwf_destroy_plan(fft_plans.spectrum_plan);
- fft_plans.spectrum_plan =
- fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
- break;
- case XTRACT_AUTOCORRELATION_FFT:
- if(fft_plans.autocorrelation_fft_plan_1 != NULL)
- fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_1);
- if(fft_plans.autocorrelation_fft_plan_2 != NULL)
- fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_2);
- fft_plans.autocorrelation_fft_plan_1 =
- fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
- fft_plans.autocorrelation_fft_plan_2 =
- fftwf_plan_r2r_1d(N, input, output, FFTW_HC2R, optimisation);
- break;
- case XTRACT_DCT:
- if(fft_plans.dct_plan != NULL)
- fftwf_destroy_plan(fft_plans.dct_plan);
- fft_plans.dct_plan =
- fftwf_plan_r2r_1d(N, input, output, FFTW_REDFT10, optimisation);
- case XTRACT_MFCC:
- if(fft_plans.dct_plan != NULL)
- fftwf_destroy_plan(fft_plans.dct_plan);
- fft_plans.dct_plan =
- fftwf_plan_r2r_1d(N, output, output, FFTW_REDFT00, optimisation);
- break;
+ {
+ M = N; /* allow for zero padding */
}
- free(input);
- free(output);
+ switch(feature_name)
+ {
+ case XTRACT_SPECTRUM:
+ if(ooura_data_spectrum.initialised)
+ {
+ xtract_free_ooura(&ooura_data_spectrum);
+ }
+ xtract_init_ooura(&ooura_data_spectrum, M);
+ break;
+ case XTRACT_AUTOCORRELATION_FFT:
+ if(ooura_data_autocorrelation_fft.initialised)
+ {
+ xtract_free_ooura(&ooura_data_autocorrelation_fft);
+ }
+ xtract_init_ooura(&ooura_data_autocorrelation_fft, M);
+ break;
+ case XTRACT_DCT:
+ if(ooura_data_dct.initialised)
+ {
+ xtract_free_ooura(&ooura_data_dct);
+ }
+ xtract_init_ooura(&ooura_data_dct, M);
+ case XTRACT_MFCC:
+ if(ooura_data_mfcc.initialised)
+ {
+ xtract_free_ooura(&ooura_data_mfcc);
+ }
+ xtract_init_ooura(&ooura_data_mfcc, M);
+ break;
+ }
return XTRACT_SUCCESS;
-
}
-void xtract_free_fft(void){
- if(fft_plans.spectrum_plan != NULL)
- fftwf_destroy_plan(fft_plans.spectrum_plan);
- if(fft_plans.autocorrelation_fft_plan_1 != NULL)
- fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_1);
- if(fft_plans.autocorrelation_fft_plan_2 != NULL)
- fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_2);
- if(fft_plans.dct_plan != NULL)
- fftwf_destroy_plan(fft_plans.dct_plan);
-// fftwf_cleanup();
+void xtract_free_fft(void)
+{
+ if(ooura_data_spectrum.initialised)
+ {
+ xtract_free_ooura(&ooura_data_spectrum);
+ }
+ if(ooura_data_autocorrelation_fft.initialised)
+ {
+ xtract_free_ooura(&ooura_data_autocorrelation_fft);
+ }
+ if(ooura_data_dct.initialised)
+ {
+ xtract_free_ooura(&ooura_data_dct);
+ }
+ if(ooura_data_mfcc.initialised)
+ {
+ xtract_free_ooura(&ooura_data_mfcc);
+ }
}
-#endif
-
-int xtract_init_bark(int N, float sr, int *band_limits){
+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)*/
@@ -230,65 +253,62 @@ int xtract_init_bark(int N, float sr, int *band_limits){
return XTRACT_SUCCESS;
}
-float *xtract_init_window(const int N, const int type){
-
+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;
+ 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){
-
+void xtract_free_window(float *window)
+{
free(window);
-
}
#ifdef __GNUC__
__attribute__((constructor)) void init()
#else
- void _init()·
+void _init()·
#endif
{
-#ifdef XTRACT_FFT
- fft_plans.spectrum_plan = NULL;
- fft_plans.autocorrelation_fft_plan_1 = NULL;
- fft_plans.autocorrelation_fft_plan_2 = NULL;
- fft_plans.dct_plan = NULL;
-#endif
+ ooura_data_dct.initialised = false;
+ ooura_data_spectrum.initialised = false;
+ ooura_data_autocorrelation_fft.initialised = false;
+ ooura_data_mfcc.initialised = false;
}