annotate src/init.c @ 107:3e648eec95cb

- Added new helper functions: xtract_windowed() and xtract_features_from_subframes() - Added windowing functions (window.c)
author Jamie Bullock <jamie@postlude.co.uk>
date Fri, 28 Dec 2007 19:34:51 +0000
parents 7a5859764ccd
children c8502708853b
rev   line source
jamie@1 1 /* libxtract feature extraction library
jamie@1 2 *
jamie@1 3 * Copyright (C) 2006 Jamie Bullock
jamie@1 4 *
jamie@1 5 * This program is free software; you can redistribute it and/or modify
jamie@1 6 * it under the terms of the GNU General Public License as published by
jamie@1 7 * the Free Software Foundation; either version 2 of the License, or
jamie@1 8 * (at your option) any later version.
jamie@1 9 *
jamie@1 10 * This program is distributed in the hope that it will be useful,
jamie@1 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
jamie@1 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
jamie@1 13 * GNU General Public License for more details.
jamie@1 14 *
jamie@1 15 * You should have received a copy of the GNU General Public License
jamie@1 16 * along with this program; if not, write to the Free Software
jamie@1 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
jamie@1 18 * USA.
jamie@1 19 */
jamie@1 20
jamie@107 21 /* init.c: defines initialisation and free functions. Also contains library constructor routine. */
jamie@1 22
jamie@98 23 #ifdef HAVE_CONFIG_H
jamie@98 24 # include <config.h>
jamie@98 25 #endif
jamie@98 26
jamie@1 27 #include <math.h>
jamie@26 28 #include <stdlib.h>
jamie@1 29
jamie@98 30 #include "xtract/libxtract.h"
jamie@107 31 #include "xtract_window_private.h"
jamie@102 32 #define DEFINE_GLOBALS
jamie@98 33 #include "xtract_globals_private.h"
jamie@98 34
jamie@98 35 #ifdef XTRACT_FFT
jamie@98 36 #include <fftw3.h>
jamie@98 37
jamie@98 38 #ifndef XTRACT_FFT_OPTIMISATION_LEVEL
jamie@98 39 /* This should never happen */
jamie@98 40 #define XTRACT_FFT_OPTIMISATION_LEVEL 1
jamie@98 41 #endif
jamie@98 42
jamie@43 43 int xtract_init_mfcc(int N, float nyquist, int style, float freq_min, float freq_max, int freq_bands, float **fft_tables){
jamie@1 44
jamie@39 45 int n, i, k, *fft_peak, M, next_peak;
jamie@1 46 float norm, mel_freq_max, mel_freq_min, norm_fact, height, inc, val,
jamie@107 47 freq_bw_mel, *mel_peak, *height_norm, *lin_peak;
jamie@1 48
jamie@1 49 mel_peak = height_norm = lin_peak = NULL;
jamie@1 50 fft_peak = NULL;
jamie@1 51 norm = 1;
jamie@1 52
jamie@1 53 mel_freq_max = 1127 * log(1 + freq_max / 700);
jamie@1 54 mel_freq_min = 1127 * log(1 + freq_min / 700);
jamie@1 55 freq_bw_mel = (mel_freq_max - mel_freq_min) / freq_bands;
jamie@1 56
jamie@1 57 mel_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
jamie@1 58 /* +2 for zeros at start and end */
jamie@1 59 lin_peak = (float *)malloc((freq_bands + 2) * sizeof(float));
jamie@1 60 fft_peak = (int *)malloc((freq_bands + 2) * sizeof(int));
jamie@1 61 height_norm = (float *)malloc(freq_bands * sizeof(float));
jamie@1 62
jamie@1 63 if(mel_peak == NULL || height_norm == NULL ||
jamie@107 64 lin_peak == NULL || fft_peak == NULL)
jamie@107 65 return XTRACT_MALLOC_FAILED;
jamie@107 66
jamie@1 67 M = N >> 1;
jamie@1 68
jamie@1 69 mel_peak[0] = mel_freq_min;
danstowell@95 70 lin_peak[0] = freq_min; // === 700 * (exp(mel_peak[0] / 1127) - 1);
jamie@1 71 fft_peak[0] = lin_peak[0] / nyquist * M;
jamie@1 72
jamie@1 73
danstowell@100 74 for (n = 1; n < freq_bands + 2; n++){
danstowell@100 75 //roll out peak locations - mel, linear and linear on fft window scale
jamie@1 76 mel_peak[n] = mel_peak[n - 1] + freq_bw_mel;
jamie@1 77 lin_peak[n] = 700 * (exp(mel_peak[n] / 1127) -1);
jamie@1 78 fft_peak[n] = lin_peak[n] / nyquist * M;
jamie@1 79 }
jamie@1 80
jamie@1 81 for (n = 0; n < freq_bands; n++){
danstowell@100 82 //roll out normalised gain of each peak
jamie@56 83 if (style == XTRACT_EQUAL_GAIN){
jamie@1 84 height = 1;
jamie@1 85 norm_fact = norm;
jamie@1 86 }
jamie@1 87 else{
jamie@1 88 height = 2 / (lin_peak[n + 2] - lin_peak[n]);
jamie@1 89 norm_fact = norm / (2 / (lin_peak[2] - lin_peak[0]));
jamie@1 90 }
jamie@1 91 height_norm[n] = height * norm_fact;
jamie@1 92 }
jamie@1 93
jamie@1 94 i = 0;
jamie@107 95
jamie@1 96 for(n = 0; n < freq_bands; n++){
jamie@107 97
jamie@107 98 // calculate the rise increment
danstowell@95 99 if(n==0)
danstowell@95 100 inc = height_norm[n] / fft_peak[n];
danstowell@95 101 else
jamie@1 102 inc = height_norm[n] / (fft_peak[n] - fft_peak[n - 1]);
jamie@1 103 val = 0;
jamie@107 104
jamie@107 105 // zero the start of the array
jamie@107 106 for(k = 0; k < i; k++)
jamie@107 107 fft_tables[n][k] = 0.f;
jamie@107 108
jamie@107 109 // fill in the rise
jamie@1 110 for(; i <= fft_peak[n]; i++){
jamie@1 111 fft_tables[n][i] = val;
jamie@1 112 val += inc;
jamie@1 113 }
jamie@107 114
danstowell@95 115 // calculate the fall increment
jamie@1 116 inc = height_norm[n] / (fft_peak[n + 1] - fft_peak[n]);
jamie@107 117
jamie@1 118 val = 0;
jamie@107 119 next_peak = fft_peak[n + 1];
jamie@107 120
jamie@107 121 // reverse fill the 'fall'
jamie@39 122 for(i = next_peak; i > fft_peak[n]; i--){
jamie@1 123 fft_tables[n][i] = val;
jamie@1 124 val += inc;
jamie@1 125 }
jamie@39 126
jamie@107 127 // zero the rest of the array
jamie@107 128 for(k = next_peak + 1; k < N; k++)
jamie@107 129 fft_tables[n][k] = 0.f;
jamie@1 130 }
jamie@1 131
jamie@98 132
jamie@98 133 /* Initialise the fft_plan for the DCT */
jamie@98 134 xtract_init_fft(freq_bands, XTRACT_MFCC);
jamie@98 135
jamie@1 136 free(mel_peak);
jamie@1 137 free(lin_peak);
jamie@1 138 free(height_norm);
jamie@1 139 free(fft_peak);
jamie@1 140
jamie@56 141 return XTRACT_SUCCESS;
jamie@1 142
jamie@1 143 }
jamie@1 144
jamie@98 145 int xtract_init_fft(int N, int feature_name){
jamie@98 146
jamie@98 147 float *input, *output;
jamie@98 148 int optimisation;
jamie@107 149
jamie@98 150 input = output = NULL;
jamie@107 151
jamie@98 152 fprintf(stderr, "Optimisation level: %d\n", XTRACT_FFT_OPTIMISATION_LEVEL);
jamie@98 153
jamie@98 154 if(XTRACT_FFT_OPTIMISATION_LEVEL == 0)
jamie@98 155 optimisation = FFTW_ESTIMATE;
jamie@98 156 else if(XTRACT_FFT_OPTIMISATION_LEVEL == 1)
jamie@98 157 optimisation = FFTW_MEASURE;
jamie@98 158 else if(XTRACT_FFT_OPTIMISATION_LEVEL == 2)
jamie@98 159 optimisation = FFTW_PATIENT;
jamie@98 160 else
jamie@98 161 optimisation = FFTW_MEASURE; /* The default */
jamie@98 162
jamie@98 163 if(feature_name == XTRACT_AUTOCORRELATION_FFT)
jamie@98 164 N <<= 1;
jamie@98 165
jamie@98 166 input = malloc(N * sizeof(float));
jamie@98 167 output = malloc(N * sizeof(float));
jamie@98 168
jamie@98 169 switch(feature_name){
jamie@98 170 case XTRACT_SPECTRUM:
jamie@102 171 if(fft_plans.spectrum_plan != NULL)
jamie@102 172 fftwf_destroy_plan(fft_plans.spectrum_plan);
jamie@102 173 fft_plans.spectrum_plan =
jamie@98 174 fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
jamie@98 175 break;
jamie@98 176 case XTRACT_AUTOCORRELATION_FFT:
jamie@102 177 if(fft_plans.autocorrelation_fft_plan_1 != NULL)
jamie@102 178 fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_1);
jamie@102 179 if(fft_plans.autocorrelation_fft_plan_2 != NULL)
jamie@102 180 fftwf_destroy_plan(fft_plans.autocorrelation_fft_plan_2);
jamie@102 181 fft_plans.autocorrelation_fft_plan_1 =
jamie@98 182 fftwf_plan_r2r_1d(N, input, output, FFTW_R2HC, optimisation);
jamie@102 183 fft_plans.autocorrelation_fft_plan_2 =
jamie@98 184 fftwf_plan_r2r_1d(N, input, output, FFTW_HC2R, optimisation);
jamie@98 185 break;
jamie@98 186 case XTRACT_DCT:
jamie@102 187 if(fft_plans.dct_plan != NULL)
jamie@102 188 fftwf_destroy_plan(fft_plans.dct_plan);
jamie@102 189 fft_plans.dct_plan =
jamie@98 190 fftwf_plan_r2r_1d(N, input, output, FFTW_REDFT00, optimisation);
jamie@98 191 case XTRACT_MFCC:
jamie@102 192 if(fft_plans.dct_plan != NULL)
jamie@102 193 fftwf_destroy_plan(fft_plans.dct_plan);
jamie@102 194 fft_plans.dct_plan =
jamie@98 195 fftwf_plan_r2r_1d(N, output, output, FFTW_REDFT00, optimisation);
jamie@98 196 break;
jamie@98 197 }
jamie@98 198
jamie@98 199 free(input);
jamie@98 200 free(output);
jamie@98 201
jamie@98 202 return XTRACT_SUCCESS;
jamie@98 203
jamie@98 204 }
jamie@98 205
jamie@98 206 #endif
jamie@98 207
jamie@59 208 int xtract_init_bark(int N, float sr, int *band_limits){
jamie@1 209
jamie@38 210 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)*/
jamie@1 211
jamie@59 212 int bands = XTRACT_BARK_BANDS;
jamie@107 213
jamie@1 214 while(bands--)
jamie@59 215 band_limits[bands] = edges[bands] / sr * N;
jamie@107 216 /*FIX shohuld use rounding, but couldn't get it to work */
jamie@38 217
jamie@56 218 return XTRACT_SUCCESS;
jamie@1 219 }
jamie@98 220
jamie@107 221 float *xtract_init_window(const int N, const int type){
jamie@107 222
jamie@107 223 float *window;
jamie@107 224
jamie@107 225 window = malloc(N * sizeof(float));
jamie@107 226
jamie@107 227 switch (type) {
jamie@107 228 case XTRACT_GAUSS:
jamie@107 229 gauss(window, N, 0.4);
jamie@107 230 break;
jamie@107 231 case XTRACT_HAMMING:
jamie@107 232 hamming(window, N);
jamie@107 233 break;
jamie@107 234 case XTRACT_HANN:
jamie@107 235 hann(window, N);
jamie@107 236 break;
jamie@107 237 case XTRACT_BARTLETT:
jamie@107 238 bartlett(window, N);
jamie@107 239 break;
jamie@107 240 case XTRACT_TRIANGULAR:
jamie@107 241 triangular(window, N);
jamie@107 242 break;
jamie@107 243 case XTRACT_BARTLETT_HANN:
jamie@107 244 bartlett_hann(window, N);
jamie@107 245 break;
jamie@107 246 case XTRACT_BLACKMAN:
jamie@107 247 blackman(window, N);
jamie@107 248 break;
jamie@107 249 case XTRACT_KAISER:
jamie@107 250 kaiser(window, N, 3 * PI);
jamie@107 251 break;
jamie@107 252 case XTRACT_BLACKMAN_HARRIS:
jamie@107 253 blackman_harris(window, N);
jamie@107 254 break;
jamie@107 255 default:
jamie@107 256 hann(window, N);
jamie@107 257 break;
jamie@107 258 }
jamie@107 259
jamie@107 260 return window;
jamie@107 261
jamie@107 262 }
jamie@107 263
jamie@107 264 void xtract_free_window(float *window){
jamie@107 265
jamie@107 266 free(window);
jamie@107 267
jamie@107 268 }
jamie@107 269
jamie@102 270 #ifdef __GNUC__
jamie@102 271 __attribute__((constructor)) void init()
jamie@102 272 #else
jamie@102 273 void _init()ยท
jamie@102 274 #endif
jamie@102 275 {
jamie@102 276 fft_plans.spectrum_plan = NULL;
jamie@102 277 fft_plans.autocorrelation_fft_plan_1 = NULL;
jamie@102 278 fft_plans.autocorrelation_fft_plan_2 = NULL;
jamie@102 279 fft_plans.dct_plan = NULL;
jamie@102 280 }