annotate src/vector.c @ 75:ee2e1acbf2a8

Fixed autocorrelation_fft() it now gives comparable output to autocorrelation()
author Jamie Bullock <jamie@postlude.co.uk>
date Fri, 20 Apr 2007 08:49:49 +0000
parents de94190a63b7
children f913cf823628
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@1 21
jamie@1 22 /* xtract_vector.c: defines functions that extract a feature as a single value from an input vector */
jamie@1 23
jamie@1 24 #include "xtract/libxtract.h"
jamie@56 25 #include "xtract_macros_private.h"
jamie@1 26 #include <math.h>
jamie@43 27 #include <string.h>
jamie@43 28 #include <stdlib.h>
jamie@30 29
jamie@30 30 #ifdef XTRACT_FFT
jamie@30 31
jamie@1 32 #include <fftw3.h>
jamie@1 33
jamie@54 34 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 35
jamie@56 36 float *input, *rfft, q, temp;
jamie@43 37 size_t bytes;
jamie@70 38 int n , NxN, M, vector, withDC;
jamie@1 39 fftwf_plan plan;
jamie@1 40
jamie@54 41 M = N >> 1;
jamie@56 42 NxN = XTRACT_SQ(N);
jamie@70 43 withDC = 0;
jamie@54 44
jamie@54 45 rfft = (float *)fftwf_malloc(N * sizeof(float));
jamie@43 46 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 47 input = memcpy(input, data, bytes);
jamie@1 48
jamie@56 49 q = *(float *)argv;
jamie@54 50 vector = (int)*((float *)argv+1);
jamie@70 51 withDC = (int)*((float *)argv+2);
jamie@46 52
jamie@56 53 XTRACT_CHECK_q;
jamie@46 54
jamie@54 55 plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 56
jamie@1 57 fftwf_execute(plan);
jamie@54 58
jamie@54 59 switch(vector){
jamie@67 60
jamie@56 61 case XTRACT_LOG_MAGNITUDE_SPECTRUM:
jamie@67 62 for(n = 1; n < M; n++){
jamie@67 63 if ((temp = XTRACT_SQ(rfft[n]) +
jamie@70 64 XTRACT_SQ(rfft[N - n])) > XTRACT_LOG_LIMIT)
jamie@54 65 temp = log(sqrt(temp) / N);
jamie@54 66 else
jamie@56 67 temp = XTRACT_LOG_LIMIT_DB;
jamie@70 68 if(withDC) {
jamie@70 69 result[n] =
jamie@70 70 /*Normalise*/
jamie@70 71 (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 72 XTRACT_DB_SCALE_OFFSET;
jamie@70 73 result[M + n + 1] = n * q;
jamie@70 74 }
jamie@70 75 else {
jamie@70 76 result[n - 1] =
jamie@70 77 (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 78 XTRACT_DB_SCALE_OFFSET;
jamie@70 79 result[M + n - 1] = n * q;
jamie@70 80 }
jamie@54 81 }
jamie@54 82 break;
jamie@67 83
jamie@56 84 case XTRACT_POWER_SPECTRUM:
jamie@67 85 for(n = 1; n < M; n++){
jamie@70 86 if(withDC){
jamie@70 87 result[n] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n]))
jamie@70 88 / NxN;
jamie@70 89 result[M + n + 1] = n * q;
jamie@70 90 }
jamie@70 91 else {
jamie@70 92 result[n - 1] =
jamie@70 93 (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN;
jamie@70 94 result[M + n - 1] = n * q;
jamie@70 95 }
jamie@54 96 }
jamie@54 97 break;
jamie@67 98
jamie@56 99 case XTRACT_LOG_POWER_SPECTRUM:
jamie@67 100 for(n = 1; n < M; n++){
jamie@70 101 if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) >
jamie@67 102 XTRACT_LOG_LIMIT)
jamie@54 103 temp = log(temp / NxN);
jamie@54 104 else
jamie@56 105 temp = XTRACT_LOG_LIMIT_DB;
jamie@70 106 if(withDC){
jamie@70 107 result[n] = (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 108 XTRACT_DB_SCALE_OFFSET;
jamie@70 109 result[M + n + 1] = n * q;
jamie@70 110 }
jamie@70 111 else {
jamie@70 112 result[n - 1] = (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 113 XTRACT_DB_SCALE_OFFSET;
jamie@70 114 result[M + n - 1] = n * q;
jamie@70 115 }
jamie@54 116 }
jamie@54 117 break;
jamie@67 118
jamie@54 119 default:
jamie@54 120 /* MAGNITUDE_SPECTRUM */
jamie@67 121 for(n = 1; n < M; n++){
jamie@70 122 if(withDC){
jamie@70 123 result[n] = sqrt(XTRACT_SQ(rfft[n]) +
jamie@70 124 XTRACT_SQ(rfft[N - n])) / N;
jamie@70 125 result[M + n + 1] = n * q;
jamie@70 126 }
jamie@70 127 else {
jamie@70 128 result[n - 1] = sqrt(XTRACT_SQ(rfft[n]) +
jamie@70 129 XTRACT_SQ(rfft[N - n])) / N;
jamie@70 130 result[M + n - 1] = n * q;
jamie@70 131 }
jamie@54 132 }
jamie@54 133 break;
jamie@1 134 }
jamie@1 135
jamie@70 136 if(withDC){
jamie@70 137 /* The DC component */
jamie@70 138 result[0] = XTRACT_SQ(rfft[0]);
jamie@70 139 result[M + 1] = 0.f;
jamie@70 140 /* The Nyquist */
jamie@70 141 result[M] = XTRACT_SQ(rfft[M]);
jamie@70 142 result[N + 1] = q * M;
jamie@70 143 }
jamie@70 144 else {
jamie@70 145 /* The Nyquist */
jamie@70 146 result[M - 1] = XTRACT_SQ(rfft[M]);
jamie@70 147 result[N - 1] = q * M;
jamie@70 148 }
jamie@1 149
jamie@1 150 fftwf_destroy_plan(plan);
jamie@54 151 fftwf_free(rfft);
jamie@43 152 free(input);
jamie@1 153
jamie@56 154 return XTRACT_SUCCESS;
jamie@1 155 }
jamie@1 156
jamie@43 157 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@1 158
jamie@75 159 float *freq, *time;
jamie@75 160 int n, M;
jamie@1 161 fftwf_plan plan;
jamie@1 162
jamie@75 163 M = N << 1;
jamie@43 164
jamie@75 165 freq = (float *)fftwf_malloc(M * sizeof(float));
jamie@75 166 /* Zero pad the input vector */
jamie@75 167 time = (float *)calloc(M, sizeof(float));
jamie@75 168 time = memcpy(time, data, N * sizeof(float));
jamie@75 169
jamie@75 170 plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 171
jamie@1 172 fftwf_execute(plan);
jamie@75 173
jamie@75 174 for(n = 1; n < M / 2; n++){
jamie@75 175 freq[n] = XTRACT_SQ(freq[n]) + XTRACT_SQ(freq[M - n]);
jamie@75 176 freq[M - n] = 0.f;
jamie@75 177 }
jamie@1 178
jamie@75 179 freq[0] = XTRACT_SQ(freq[0]);
jamie@75 180 freq[N] = XTRACT_SQ(freq[N]);
jamie@75 181
jamie@75 182 plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE);
jamie@75 183
jamie@75 184 fftwf_execute(plan);
jamie@75 185
jamie@75 186 /* Normalisation factor */
jamie@75 187 M = M * N;
jamie@75 188
jamie@75 189 for(n = 0; n < N; n++)
jamie@75 190 result[n] = time[n] / (float)M;
jamie@75 191 /* result[n] = time[n+1] / (float)M; */
jamie@75 192
jamie@1 193 fftwf_destroy_plan(plan);
jamie@75 194 fftwf_free(freq);
jamie@75 195 free(time);
jamie@38 196
jamie@56 197 return XTRACT_SUCCESS;
jamie@1 198 }
jamie@1 199
jamie@43 200 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 201
jamie@30 202 xtract_mel_filter *f;
jamie@30 203 int n, filter;
jamie@30 204
jamie@30 205 f = (xtract_mel_filter *)argv;
jamie@39 206
jamie@30 207 for(filter = 0; filter < f->n_filters; filter++){
danstowell@68 208 result[filter] = 0.f;
jamie@30 209 for(n = 0; n < N; n++){
jamie@71 210 result[filter] += data[n] * f->filters[filter][n];
jamie@30 211 }
danstowell@69 212 result[filter] = log(result[filter] < XTRACT_LOG_LIMIT ? XTRACT_LOG_LIMIT : result[filter]);
jamie@30 213 }
jamie@30 214
jamie@30 215 for(n = filter + 1; n < N; n++) result[n] = 0;
jamie@30 216
jamie@30 217 xtract_dct(result, f->n_filters, NULL, result);
jamie@43 218
jamie@56 219 return XTRACT_SUCCESS;
jamie@30 220 }
jamie@30 221
jamie@43 222 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 223
jamie@30 224 fftwf_plan plan;
jamie@43 225
jamie@30 226 plan =
danstowell@74 227 fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE);
jamie@30 228
jamie@30 229 fftwf_execute(plan);
jamie@30 230 fftwf_destroy_plan(plan);
jamie@38 231
jamie@56 232 return XTRACT_SUCCESS;
jamie@30 233 }
jamie@30 234
jamie@30 235 #else
jamie@30 236
jamie@67 237 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@30 238
danstowell@66 239 XTRACT_NEEDS_FFTW;
danstowell@66 240 return XTRACT_NO_RESULT;
jamie@30 241
jamie@30 242 }
jamie@30 243
jamie@43 244 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@30 245
danstowell@66 246 XTRACT_NEEDS_FFTW;
danstowell@66 247 return XTRACT_NO_RESULT;
jamie@30 248
jamie@30 249 }
jamie@30 250
jamie@43 251 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 252
danstowell@66 253 XTRACT_NEEDS_FFTW;
danstowell@66 254 return XTRACT_NO_RESULT;
jamie@30 255
jamie@30 256 }
jamie@30 257
jamie@43 258 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 259
danstowell@66 260 XTRACT_NEEDS_FFTW;
danstowell@66 261 return XTRACT_NO_RESULT;
jamie@30 262
jamie@30 263 }
jamie@30 264
jamie@30 265 #endif
jamie@30 266
jamie@43 267 int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){
jamie@30 268
jamie@30 269 /* Naive time domain implementation */
jamie@30 270
jamie@30 271 int n = N, i;
jamie@30 272
jamie@30 273 float corr;
jamie@30 274
jamie@30 275 while(n--){
jamie@30 276 corr = 0;
jamie@30 277 for(i = 0; i < N - n; i++){
jamie@30 278 corr += data[i] * data[i + n];
jamie@30 279 }
jamie@30 280 result[n] = corr / N;
jamie@30 281 }
jamie@38 282
jamie@56 283 return XTRACT_SUCCESS;
jamie@30 284 }
jamie@30 285
jamie@43 286 int xtract_amdf(const float *data, const int N, const void *argv, float *result){
jamie@1 287
jamie@1 288 int n = N, i;
jamie@1 289
jamie@6 290 float md, temp;
jamie@1 291
jamie@1 292 while(n--){
jamie@1 293 md = 0;
jamie@1 294 for(i = 0; i < N - n; i++){
jamie@6 295 temp = data[i] - data[i + n];
jamie@6 296 temp = (temp < 0 ? -temp : temp);
jamie@6 297 md += temp;
jamie@1 298 }
jamie@1 299 result[n] = md / N;
jamie@1 300 }
jamie@38 301
jamie@56 302 return XTRACT_SUCCESS;
jamie@1 303 }
jamie@1 304
jamie@43 305 int xtract_asdf(const float *data, const int N, const void *argv, float *result){
jamie@1 306
jamie@1 307 int n = N, i;
jamie@1 308
jamie@1 309 float sd;
jamie@1 310
jamie@1 311 while(n--){
jamie@1 312 sd = 0;
jamie@1 313 for(i = 0; i < N - n; i++){
jamie@6 314 /*sd = 1;*/
jamie@56 315 sd += XTRACT_SQ(data[i] - data[i + n]);
jamie@1 316 }
jamie@1 317 result[n] = sd / N;
jamie@1 318 }
jamie@38 319
jamie@56 320 return XTRACT_SUCCESS;
jamie@1 321 }
jamie@1 322
jamie@43 323 int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
jamie@1 324
jamie@1 325 int *limits, band, n;
jamie@1 326
jamie@1 327 limits = (int *)argv;
jamie@1 328
jamie@59 329 for(band = 0; band < XTRACT_BARK_BANDS - 1; band++){
jamie@1 330 for(n = limits[band]; n < limits[band + 1]; n++)
jamie@1 331 result[band] += data[n];
jamie@1 332 }
jamie@38 333
jamie@56 334 return XTRACT_SUCCESS;
jamie@1 335 }
jamie@1 336
jamie@52 337 int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 338
jamie@56 339 float threshold, max, y, y2, y3, p, q, *input = NULL;
jamie@43 340 size_t bytes;
jamie@59 341 int n = N, rv = XTRACT_SUCCESS;
jamie@49 342
jamie@56 343 threshold = max = y = y2 = y3 = p = q = 0.f;
jamie@1 344
jamie@1 345 if(argv != NULL){
jamie@56 346 q = ((float *)argv)[0];
jamie@55 347 threshold = ((float *)argv)[1];
jamie@1 348 }
jamie@49 349 else
jamie@56 350 rv = XTRACT_BAD_ARGV;
jamie@49 351
jamie@55 352 if(threshold < 0 || threshold > 100){
jamie@55 353 threshold = 0;
jamie@56 354 rv = XTRACT_BAD_ARGV;
jamie@1 355 }
jamie@1 356
jamie@56 357 XTRACT_CHECK_q;
jamie@49 358
jamie@43 359 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 360
jamie@43 361 if(input != NULL)
jamie@43 362 input = memcpy(input, data, bytes);
jamie@43 363 else
jamie@56 364 return XTRACT_MALLOC_FAILED;
jamie@43 365
jamie@45 366 while(n--)
jamie@56 367 max = XTRACT_MAX(max, input[n]);
jamie@1 368
jamie@55 369 threshold *= .01 * max;
jamie@1 370
jamie@1 371 result[0] = 0;
jamie@59 372 result[N] = 0;
jamie@1 373
jamie@59 374 for(n = 1; n < N; n++){
jamie@55 375 if(input[n] >= threshold){
jamie@43 376 if(input[n] > input[n - 1] && input[n] > input[n + 1]){
jamie@59 377 result[N + n] = q * (n + (p = .5 * (y = input[n-1] -
jamie@52 378 (y3 = input[n+1])) / (input[n - 1] - 2 *
jamie@52 379 (y2 = input[n]) + input[n + 1])));
jamie@52 380 result[n] = y2 - .25 * (y - y3) * p;
jamie@1 381 }
jamie@1 382 else{
jamie@1 383 result[n] = 0;
jamie@59 384 result[N + n] = 0;
jamie@1 385 }
jamie@1 386 }
jamie@1 387 else{
jamie@1 388 result[n] = 0;
jamie@59 389 result[N + n] = 0;
jamie@1 390 }
jamie@1 391 }
jamie@1 392
jamie@43 393 free(input);
jamie@56 394 return (rv ? rv : XTRACT_SUCCESS);
jamie@1 395 }
jamie@41 396
jamie@52 397 int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@38 398
jamie@38 399 int n = (N >> 1), M = n;
jamie@38 400
jamie@43 401 const float *freqs, *amps;
jamie@55 402 float f0, threshold, ratio, nearest, distance;
jamie@38 403
jamie@52 404 amps = data;
jamie@52 405 freqs = data + n;
jamie@38 406 f0 = *((float *)argv);
jamie@55 407 threshold = *((float *)argv+1);
jamie@38 408
jamie@38 409 ratio = nearest = distance = 0.f;
jamie@38 410
jamie@38 411 while(n--){
jamie@38 412 if(freqs[n]){
jamie@38 413 ratio = freqs[n] / f0;
jamie@38 414 nearest = round(ratio);
jamie@38 415 distance = fabs(nearest - ratio);
jamie@55 416 if(distance > threshold)
jamie@38 417 result[n] = result[M + n] = 0.f;
jamie@42 418 else {
jamie@52 419 result[n] = amps[n];
jamie@52 420 result[M + n] = freqs[n];
jamie@42 421 }
jamie@38 422 }
jamie@38 423 else
jamie@38 424 result[n] = result[M + n] = 0.f;
jamie@38 425 }
jamie@56 426 return XTRACT_SUCCESS;
jamie@38 427 }
jamie@38 428