annotate src/vector.c @ 150:9283aaf1ffb8

implemented optimised FFT via the Accelerate framework. closes #5
author Jamie Bullock <jamie@jamiebullock.com>
date Wed, 09 Jan 2013 23:09:34 +0000
parents e899c3a708ad
children 826eb46b2f91
rev   line source
jamie@141 1 /*
jamie@141 2 * Copyright (C) 2012 Jamie Bullock
jamie@140 3 *
jamie@141 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
jamie@141 5 * of this software and associated documentation files (the "Software"), to
jamie@141 6 * deal in the Software without restriction, including without limitation the
jamie@141 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
jamie@141 8 * sell copies of the Software, and to permit persons to whom the Software is
jamie@141 9 * furnished to do so, subject to the following conditions:
jamie@1 10 *
jamie@141 11 * The above copyright notice and this permission notice shall be included in
jamie@141 12 * all copies or substantial portions of the Software.
jamie@1 13 *
jamie@141 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jamie@141 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jamie@141 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jamie@141 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jamie@141 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
jamie@141 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
jamie@141 20 * IN THE SOFTWARE.
jamie@1 21 *
jamie@1 22 */
jamie@1 23
jamie@1 24 /* xtract_vector.c: defines functions that extract a feature as a single value from an input vector */
jamie@1 25
jamie@1 26 #include <math.h>
jamie@43 27 #include <string.h>
jamie@43 28 #include <stdlib.h>
jamie@30 29
jamie@148 30 #include "fft.h"
jamie@140 31
jamie@98 32 #include "xtract/libxtract.h"
jamie@98 33 #include "xtract_macros_private.h"
jamie@146 34 #include "xtract_globals_private.h"
jamie@98 35
jamie@146 36 int xtract_spectrum(const double *data, const int N, const void *argv, double *result)
jamie@140 37 {
jamie@1 38
jamie@140 39 int vector = 0;
jamie@140 40 int withDC = 0;
jamie@140 41 int normalise = 0;
jamie@146 42 double q = 0.0;
jamie@146 43 double temp = 0.0;
jamie@146 44 double max = 0.0;
jamie@146 45 double NxN = XTRACT_SQ(N);
jamie@146 46 double *marker = NULL;
jamie@150 47 double real = 0.0;
jamie@150 48 double imag = 0.0;
jamie@140 49 unsigned int n = 0;
jamie@140 50 unsigned int m = 0;
jamie@140 51 unsigned int M = N >> 1;
jamie@150 52 #ifndef USE_OOURA
jamie@150 53 DSPDoubleSplitComplex *fft = NULL;
jamie@150 54 #endif
jamie@98 55
jamie@146 56 q = *(double *)argv;
jamie@146 57 vector = (int)*((double *)argv+1);
jamie@146 58 withDC = (int)*((double *)argv+2);
jamie@146 59 normalise = (int)*((double *)argv+3);
jamie@105 60
jamie@56 61 XTRACT_CHECK_q;
jamie@150 62 #ifdef USE_OOURA
jamie@140 63 if(!ooura_data_spectrum.initialised)
jamie@150 64 #else
jamie@150 65 if(!vdsp_data_spectrum.initialised)
jamie@150 66 #endif
jamie@140 67 {
jamie@140 68 fprintf(stderr,
jamie@140 69 "libxtract: error: xtract_spectrum() failed, "
jamie@140 70 "fft data unitialised.\n");
jamie@98 71 return XTRACT_NO_RESULT;
jamie@98 72 }
jamie@98 73
jamie@150 74 #ifdef USE_OOURA
jamie@140 75 /* ooura is in-place
jamie@147 76 * the output format is
jamie@140 77 * a[0] - DC, a[1] - nyquist, a[2...N-1] - remaining bins
jamie@140 78 */
jamie@147 79 rdft(N, 1, data, ooura_data_spectrum.ooura_ip,
jamie@140 80 ooura_data_spectrum.ooura_w);
jamie@150 81 #else
jamie@150 82 fft = &vdsp_data_spectrum.fft;
jamie@150 83 vDSP_ctozD((DSPDoubleComplex *)data, 2, fft, 1, N >> 1);
jamie@150 84 vDSP_fft_zripD(vdsp_data_spectrum.setup, fft, 1,
jamie@150 85 vdsp_data_spectrum.log2N, FFT_FORWARD);
jamie@150 86 #endif
jamie@54 87
jamie@140 88 switch(vector)
jamie@140 89 {
jamie@67 90
jamie@120 91 case XTRACT_LOG_MAGNITUDE_SPECTRUM:
jamie@140 92 for(n = 0, m = 0; m < M; ++n, ++m)
jamie@140 93 {
jamie@150 94 marker = &result[m];
jamie@150 95
jamie@150 96 if(n==0 && !withDC) /* discard DC and keep Nyquist */
jamie@140 97 {
jamie@150 98 ++n;
jamie@150 99 #ifdef USE_OOURA
jamie@150 100 marker = &result[M-1];
jamie@150 101 #endif
jamie@140 102 }
jamie@150 103 #ifdef USE_OOURA
jamie@150 104 if(n==1 && withDC) /* discard Nyquist */
jamie@150 105 {
jamie@150 106 ++n;
jamie@150 107 }
jamie@150 108
jamie@150 109 real = data[n*2];
jamie@150 110 imag = data[n*2+1];
jamie@150 111 #else
jamie@150 112 real = fft->realp[n];
jamie@150 113 imag = fft->realp[n];
jamie@150 114 #endif
jamie@150 115
jamie@150 116 temp = XTRACT_SQ(real) + XTRACT_SQ(imag);
jamie@140 117 if (temp > XTRACT_LOG_LIMIT)
jamie@140 118 {
jamie@146 119 temp = log(sqrt(temp) / (double)N);
jamie@140 120 }
jamie@140 121 else
jamie@140 122 {
jamie@140 123 temp = XTRACT_LOG_LIMIT_DB;
jamie@140 124 }
jamie@140 125 result[m] =
jamie@140 126 /* Scaling */
jamie@140 127 (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@140 128 XTRACT_DB_SCALE_OFFSET;
jamie@111 129
jamie@140 130 XTRACT_SET_FREQUENCY;
jamie@140 131 XTRACT_GET_MAX;
jamie@140 132 }
jamie@140 133 break;
jamie@67 134
jamie@140 135 case XTRACT_POWER_SPECTRUM:
jamie@140 136 for(n = 0, m = 0; m < M; ++n, ++m)
jamie@140 137 {
jamie@150 138
jamie@150 139 marker = &result[m];
jamie@150 140
jamie@150 141 if(n==0 && !withDC) /* discard DC and keep Nyquist */
jamie@150 142 {
jamie@150 143 ++n;
jamie@150 144 #ifdef USE_OOURA
jamie@150 145 marker = &result[M-1];
jamie@150 146 #endif
jamie@150 147 }
jamie@150 148 #ifdef USE_OOURA
jamie@150 149 if(n==1 && withDC) /* discard Nyquist */
jamie@140 150 {
jamie@140 151 ++n;
jamie@120 152 }
jamie@150 153
jamie@150 154 real = data[n*2];
jamie@150 155 imag = data[n*2+1];
jamie@150 156 #else
jamie@150 157 real = fft->realp[n];
jamie@150 158 imag = fft->realp[n];
jamie@150 159 #endif
jamie@150 160
jamie@150 161 result[m] = (XTRACT_SQ(real) + XTRACT_SQ(imag)) / NxN;
jamie@140 162 XTRACT_SET_FREQUENCY;
jamie@140 163 XTRACT_GET_MAX;
jamie@140 164 }
jamie@140 165 break;
jamie@120 166
jamie@140 167 case XTRACT_LOG_POWER_SPECTRUM:
jamie@140 168 for(n = 0, m = 0; m < M; ++n, ++m)
jamie@140 169 {
jamie@150 170 marker = &result[m];
jamie@150 171
jamie@150 172 if(n==0 && !withDC) /* discard DC and keep Nyquist */
jamie@150 173 {
jamie@150 174 ++n;
jamie@150 175 #ifdef USE_OOURA
jamie@150 176 marker = &result[M-1];
jamie@150 177 #endif
jamie@150 178 }
jamie@150 179 #ifdef USE_OOURA
jamie@150 180 if(n==1 && withDC) /* discard Nyquist */
jamie@140 181 {
jamie@140 182 ++n;
jamie@120 183 }
jamie@150 184
jamie@150 185 real = data[n*2];
jamie@150 186 imag = data[n*2+1];
jamie@150 187 #else
jamie@150 188 real = fft->realp[n];
jamie@150 189 imag = fft->realp[n];
jamie@150 190 #endif
jamie@150 191
jamie@150 192 if ((temp = XTRACT_SQ(real) + XTRACT_SQ(imag)) >
jamie@140 193 XTRACT_LOG_LIMIT)
jamie@146 194 temp = log(temp / NxN);
jamie@140 195 else
jamie@140 196 temp = XTRACT_LOG_LIMIT_DB;
jamie@67 197
jamie@140 198 result[m] = (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@140 199 XTRACT_DB_SCALE_OFFSET;
jamie@140 200 XTRACT_SET_FREQUENCY;
jamie@140 201 XTRACT_GET_MAX;
jamie@140 202 }
jamie@140 203 break;
jamie@111 204
jamie@140 205 default:
jamie@140 206 /* MAGNITUDE_SPECTRUM */
jamie@140 207 for(n = 0, m = 0; m < M; ++n, ++m)
jamie@140 208 {
jamie@140 209 marker = &result[m];
jamie@140 210
jamie@140 211 if(n==0 && !withDC) /* discard DC and keep Nyquist */
jamie@140 212 {
jamie@140 213 ++n;
jamie@150 214 #ifdef USE_OOURA
jamie@140 215 marker = &result[M-1];
jamie@150 216 #endif
jamie@120 217 }
jamie@150 218 #ifdef USE_OOURA
jamie@140 219 if(n==1 && withDC) /* discard Nyquist */
jamie@140 220 {
jamie@140 221 ++n;
jamie@140 222 }
jamie@150 223 real = data[n*2];
jamie@150 224 imag = data[n*2+1];
jamie@150 225 #else
jamie@150 226 real = fft->realp[n];
jamie@150 227 imag = fft->realp[n];
jamie@150 228 #endif
jamie@150 229 *marker = sqrt(XTRACT_SQ(real) + XTRACT_SQ(imag)) / (double)N;
jamie@111 230
jamie@140 231 XTRACT_SET_FREQUENCY;
jamie@140 232 XTRACT_GET_MAX;
jamie@140 233 }
jamie@140 234 break;
jamie@70 235 }
jamie@105 236
jamie@140 237 if(normalise)
jamie@140 238 {
jamie@105 239 for(n = 0; n < M; n++)
jamie@105 240 result[n] /= max;
jamie@105 241 }
jamie@105 242
jamie@56 243 return XTRACT_SUCCESS;
jamie@1 244 }
jamie@1 245
jamie@146 246 int xtract_autocorrelation_fft(const double *data, const int N, const void *argv, double *result)
jamie@140 247 {
jamie@120 248
jamie@140 249 double *rfft = NULL;
jamie@140 250 int n = 0;
jamie@140 251 int M = 0;
jamie@150 252 double M_double = 0.0;
jamie@150 253 #ifndef USE_OOURA
jamie@150 254 DSPDoubleSplitComplex *fft = NULL;
jamie@150 255 #endif
jamie@1 256
jamie@75 257 M = N << 1;
jamie@43 258
jamie@75 259 /* Zero pad the input vector */
jamie@140 260 rfft = (double *)calloc(M, sizeof(double));
jamie@146 261 memcpy(rfft, data, N * sizeof(double));
jamie@75 262
jamie@150 263 #ifdef USE_OOURA
jamie@140 264 rdft(M, 1, rfft, ooura_data_autocorrelation_fft.ooura_ip,
jamie@140 265 ooura_data_autocorrelation_fft.ooura_w);
jamie@1 266
jamie@150 267 for(n = 2; n < M; ++n)
jamie@140 268 {
jamie@140 269 rfft[n*2] = XTRACT_SQ(rfft[n*2]) + XTRACT_SQ(rfft[n*2+1]);
jamie@146 270 rfft[n*2+1] = 0.0;
jamie@75 271 }
jamie@120 272
jamie@140 273 rfft[0] = XTRACT_SQ(rfft[0]);
jamie@140 274 rfft[1] = XTRACT_SQ(rfft[1]);
jamie@75 275
jamie@140 276 rdft(M, -1, rfft, ooura_data_autocorrelation_fft.ooura_ip,
jamie@140 277 ooura_data_autocorrelation_fft.ooura_w);
jamie@120 278
jamie@150 279 #else
jamie@150 280 /* vDSP has its own autocorrelation function, but it doesn't fit the
jamie@150 281 * LibXtract model, e.g. we can't guarantee it's going to use
jamie@150 282 * an FFT for all values of N */
jamie@150 283 fft = &vdsp_data_autocorrelation_fft.fft;
jamie@150 284 vDSP_ctozD((DSPDoubleComplex *)data, 2, fft, 1, N);
jamie@150 285 vDSP_fft_zripD(vdsp_data_autocorrelation_fft.setup, fft, 1,
jamie@150 286 vdsp_data_autocorrelation_fft.log2N, FFT_FORWARD);
jamie@150 287
jamie@150 288 for(n = 0; n < N; ++n)
jamie@150 289 {
jamie@150 290 fft->realp[n] = XTRACT_SQ(fft->realp[n]) + XTRACT_SQ(fft->imagp[n]);
jamie@150 291 fft->imagp[n] = 0.0;
jamie@150 292 }
jamie@150 293
jamie@150 294 vDSP_fft_zripD(vdsp_data_autocorrelation_fft.setup, fft, 1,
jamie@150 295 vdsp_data_autocorrelation_fft.log2N, FFT_INVERSE);
jamie@150 296 #endif
jamie@150 297
jamie@75 298 /* Normalisation factor */
jamie@75 299 M = M * N;
jamie@75 300
jamie@150 301 #ifdef USE_OOURA
jamie@75 302 for(n = 0; n < N; n++)
jamie@146 303 result[n] = rfft[n] / (double)M;
jamie@140 304 free(rfft);
jamie@150 305 #else
jamie@150 306 M_double = (double)M;
jamie@150 307 vDSP_ztocD(fft, 1, (DOUBLE_COMPLEX *)result, 2, N);
jamie@150 308 vDSP_vsdivD(result, 1, &M_double, result, 1, N);
jamie@150 309 #endif
jamie@38 310
jamie@56 311 return XTRACT_SUCCESS;
jamie@1 312 }
jamie@1 313
jamie@146 314 int xtract_mfcc(const double *data, const int N, const void *argv, double *result)
jamie@140 315 {
jamie@30 316
jamie@30 317 xtract_mel_filter *f;
jamie@30 318 int n, filter;
jamie@30 319
jamie@30 320 f = (xtract_mel_filter *)argv;
jamie@120 321
jamie@140 322 for(filter = 0; filter < f->n_filters; filter++)
jamie@140 323 {
jamie@146 324 result[filter] = 0.0;
jamie@140 325 for(n = 0; n < N; n++)
jamie@140 326 {
jamie@71 327 result[filter] += data[n] * f->filters[filter][n];
jamie@30 328 }
jamie@146 329 result[filter] = log(result[filter] < XTRACT_LOG_LIMIT ? XTRACT_LOG_LIMIT : result[filter]);
jamie@30 330 }
jamie@30 331
jamie@30 332 xtract_dct(result, f->n_filters, NULL, result);
jamie@120 333
jamie@56 334 return XTRACT_SUCCESS;
jamie@30 335 }
jamie@30 336
jamie@146 337 int xtract_dct(const double *data, const int N, const void *argv, double *result)
jamie@140 338 {
jamie@120 339
jamie@148 340 int n;
jamie@148 341 int m;
jamie@148 342 double *temp = calloc(N, sizeof(double));
jamie@120 343
jamie@148 344 for (n = 0; n < N; ++n)
jamie@148 345 {
jamie@148 346 for(m = 1; m <= N; ++m) {
jamie@148 347 temp[n] += data[m - 1] * cos(M_PI * (n / (double)N) * (m - 0.5));
jamie@140 348 }
jamie@148 349 }
jamie@120 350
jamie@148 351 memcpy(result, temp, N * sizeof(double));
jamie@148 352 free(temp);
jamie@148 353
jamie@148 354 return XTRACT_SUCCESS;
jamie@30 355 }
jamie@30 356
jamie@146 357 int xtract_autocorrelation(const double *data, const int N, const void *argv, double *result)
jamie@140 358 {
jamie@30 359
jamie@30 360 /* Naive time domain implementation */
jamie@120 361
jamie@30 362 int n = N, i;
jamie@120 363
jamie@146 364 double corr;
jamie@30 365
jamie@140 366 while(n--)
jamie@140 367 {
jamie@120 368 corr = 0;
jamie@140 369 for(i = 0; i < N - n; i++)
jamie@140 370 {
jamie@30 371 corr += data[i] * data[i + n];
jamie@30 372 }
jamie@30 373 result[n] = corr / N;
jamie@30 374 }
jamie@38 375
jamie@56 376 return XTRACT_SUCCESS;
jamie@30 377 }
jamie@30 378
jamie@146 379 int xtract_amdf(const double *data, const int N, const void *argv, double *result)
jamie@140 380 {
jamie@1 381
jamie@1 382 int n = N, i;
jamie@120 383
jamie@146 384 double md, temp;
jamie@1 385
jamie@140 386 while(n--)
jamie@140 387 {
jamie@146 388 md = 0.0;
jamie@140 389 for(i = 0; i < N - n; i++)
jamie@140 390 {
jamie@6 391 temp = data[i] - data[i + n];
jamie@120 392 temp = (temp < 0 ? -temp : temp);
jamie@120 393 md += temp;
jamie@1 394 }
jamie@146 395 result[n] = md / (double)N;
jamie@1 396 }
jamie@38 397
jamie@56 398 return XTRACT_SUCCESS;
jamie@1 399 }
jamie@1 400
jamie@146 401 int xtract_asdf(const double *data, const int N, const void *argv, double *result)
jamie@140 402 {
jamie@120 403
jamie@1 404 int n = N, i;
jamie@120 405
jamie@146 406 double sd;
jamie@1 407
jamie@140 408 while(n--)
jamie@140 409 {
jamie@146 410 sd = 0.0;
jamie@140 411 for(i = 0; i < N - n; i++)
jamie@140 412 {
jamie@6 413 /*sd = 1;*/
jamie@56 414 sd += XTRACT_SQ(data[i] - data[i + n]);
jamie@1 415 }
jamie@146 416 result[n] = sd / (double)N;
jamie@1 417 }
jamie@38 418
jamie@56 419 return XTRACT_SUCCESS;
jamie@1 420 }
jamie@1 421
jamie@146 422 int xtract_bark_coefficients(const double *data, const int N, const void *argv, double *result)
jamie@140 423 {
jamie@1 424
jamie@1 425 int *limits, band, n;
jamie@1 426
jamie@1 427 limits = (int *)argv;
jamie@120 428
jamie@140 429 for(band = 0; band < XTRACT_BARK_BANDS - 1; band++)
jamie@140 430 {
jamie@146 431 result[band] = 0.0;
jamie@1 432 for(n = limits[band]; n < limits[band + 1]; n++)
jamie@1 433 result[band] += data[n];
jamie@1 434 }
jamie@38 435
jamie@56 436 return XTRACT_SUCCESS;
jamie@1 437 }
jamie@1 438
jamie@146 439 int xtract_peak_spectrum(const double *data, const int N, const void *argv, double *result)
jamie@140 440 {
jamie@1 441
jamie@146 442 double threshold, max, y, y2, y3, p, q, *input = NULL;
jamie@43 443 size_t bytes;
jamie@59 444 int n = N, rv = XTRACT_SUCCESS;
jamie@49 445
jamie@146 446 threshold = max = y = y2 = y3 = p = q = 0.0;
jamie@120 447
jamie@140 448 if(argv != NULL)
jamie@140 449 {
jamie@146 450 q = ((double *)argv)[0];
jamie@146 451 threshold = ((double *)argv)[1];
jamie@1 452 }
jamie@49 453 else
jamie@56 454 rv = XTRACT_BAD_ARGV;
jamie@49 455
jamie@140 456 if(threshold < 0 || threshold > 100)
jamie@140 457 {
jamie@55 458 threshold = 0;
jamie@56 459 rv = XTRACT_BAD_ARGV;
jamie@1 460 }
jamie@1 461
jamie@56 462 XTRACT_CHECK_q;
jamie@49 463
jamie@146 464 input = (double *)calloc(N, sizeof(double));
jamie@98 465
jamie@146 466 bytes = N * sizeof(double);
jamie@43 467
jamie@43 468 if(input != NULL)
jamie@120 469 input = memcpy(input, data, bytes);
jamie@43 470 else
jamie@120 471 return XTRACT_MALLOC_FAILED;
jamie@43 472
jamie@45 473 while(n--)
jamie@56 474 max = XTRACT_MAX(max, input[n]);
jamie@120 475
jamie@55 476 threshold *= .01 * max;
jamie@1 477
jamie@1 478 result[0] = 0;
jamie@59 479 result[N] = 0;
jamie@1 480
jamie@140 481 for(n = 1; n < N; n++)
jamie@140 482 {
jamie@140 483 if(input[n] >= threshold)
jamie@140 484 {
jamie@140 485 if(input[n] > input[n - 1] && n + 1 < N && input[n] > input[n + 1])
jamie@140 486 {
jamie@140 487 result[N + n] = q * (n + (p = .5 * ((y = input[n-1]) -
jamie@140 488 (y3 = input[n+1])) / (input[n - 1] - 2 *
jamie@140 489 (y2 = input[n]) + input[n + 1])));
jamie@52 490 result[n] = y2 - .25 * (y - y3) * p;
jamie@1 491 }
jamie@140 492 else
jamie@140 493 {
jamie@1 494 result[n] = 0;
jamie@59 495 result[N + n] = 0;
jamie@1 496 }
jamie@1 497 }
jamie@140 498 else
jamie@140 499 {
jamie@1 500 result[n] = 0;
jamie@59 501 result[N + n] = 0;
jamie@1 502 }
jamie@140 503 }
jamie@120 504
jamie@43 505 free(input);
jamie@56 506 return (rv ? rv : XTRACT_SUCCESS);
jamie@1 507 }
jamie@120 508
jamie@146 509 int xtract_harmonic_spectrum(const double *data, const int N, const void *argv, double *result)
jamie@140 510 {
jamie@120 511
jamie@140 512 int n = (N >> 1), M = n;
jamie@38 513
jamie@146 514 const double *freqs, *amps;
jamie@146 515 double f0, threshold, ratio, nearest, distance;
jamie@38 516
jamie@52 517 amps = data;
jamie@52 518 freqs = data + n;
jamie@146 519 f0 = *((double *)argv);
jamie@146 520 threshold = *((double *)argv+1);
jamie@38 521
jamie@146 522 ratio = nearest = distance = 0.0;
jamie@38 523
jamie@140 524 while(n--)
jamie@140 525 {
jamie@140 526 if(freqs[n])
jamie@140 527 {
jamie@120 528 ratio = freqs[n] / f0;
jamie@146 529 nearest = round(ratio);
jamie@120 530 distance = fabs(nearest - ratio);
jamie@120 531 if(distance > threshold)
jamie@146 532 result[n] = result[M + n] = 0.0;
jamie@140 533 else
jamie@140 534 {
jamie@120 535 result[n] = amps[n];
jamie@120 536 result[M + n] = freqs[n];
jamie@120 537 }
jamie@120 538 }
jamie@120 539 else
jamie@146 540 result[n] = result[M + n] = 0.0;
jamie@38 541 }
jamie@56 542 return XTRACT_SUCCESS;
jamie@38 543 }
jamie@120 544
jamie@146 545 int xtract_lpc(const double *data, const int N, const void *argv, double *result)
jamie@140 546 {
jamie@104 547
jamie@104 548 int i, j, k, M, L;
jamie@146 549 double r = 0.0,
jamie@146 550 error = 0.0;
jamie@104 551
jamie@146 552 double *ref = NULL,
jamie@140 553 *lpc = NULL ;
jamie@104 554
jamie@104 555 error = data[0];
jamie@104 556 k = N; /* The length of *data */
jamie@104 557 L = N - 1; /* The number of LPC coefficients */
jamie@104 558 M = L * 2; /* The length of *result */
jamie@104 559 ref = result;
jamie@104 560 lpc = result+L;
jamie@113 561
jamie@140 562 if(error == 0.0)
jamie@140 563 {
jamie@146 564 memset(result, 0, M * sizeof(double));
jamie@104 565 return XTRACT_NO_RESULT;
jamie@104 566 }
jamie@113 567
jamie@146 568 memset(result, 0, M * sizeof(double));
jamie@104 569
jamie@140 570 for (i = 0; i < L; i++)
jamie@140 571 {
jamie@104 572
jamie@104 573 /* Sum up this iteration's reflection coefficient. */
jamie@104 574 r = -data[i + 1];
jamie@140 575 for (j = 0; j < i; j++)
jamie@104 576 r -= lpc[j] * data[i - j];
jamie@104 577 ref[i] = r /= error;
jamie@104 578
jamie@104 579 /* Update LPC coefficients and total error. */
jamie@104 580 lpc[i] = r;
jamie@140 581 for (j = 0; j < i / 2; j++)
jamie@140 582 {
jamie@146 583 double tmp = lpc[j];
jamie@104 584 lpc[j] = r * lpc[i - 1 - j];
jamie@104 585 lpc[i - 1 - j] += r * tmp;
jamie@104 586 }
jamie@104 587 if (i % 2) lpc[j] += lpc[j] * r;
jamie@104 588
jamie@104 589 error *= 1 - r * r;
jamie@104 590 }
jamie@104 591
jamie@104 592 return XTRACT_SUCCESS;
jamie@104 593 }
jamie@104 594
jamie@146 595 int xtract_lpcc(const double *data, const int N, const void *argv, double *result)
jamie@140 596 {
jamie@104 597
jamie@104 598 /* Given N lpc coefficients extract an LPC cepstrum of size argv[0] */
jamie@104 599 /* Based on an an algorithm by rabiner and Juang */
jamie@104 600
jamie@104 601 int n, k;
jamie@146 602 double sum;
jamie@104 603 int order = N - 1; /* Eventually change this to Q = 3/2 p as suggested in Rabiner */
jamie@140 604 int cep_length;
jamie@120 605
jamie@104 606 if(argv == NULL)
jamie@115 607 cep_length = N - 1; /* FIX: if we're going to have default values, they should come from the descriptor */
jamie@104 608 else
jamie@115 609 cep_length = *(int *)argv;
jamie@146 610 //cep_length = (int)((double *)argv)[0];
jamie@104 611
jamie@146 612 memset(result, 0, cep_length * sizeof(double));
jamie@104 613
jamie@140 614 for (n = 1; n <= order && n <= cep_length; n++)
jamie@140 615 {
jamie@146 616 sum = 0.0;
jamie@104 617 for (k = 1; k < n; k++)
jamie@104 618 sum += k * result[k-1] * data[n - k];
jamie@104 619 result[n-1] = data[n] + sum / n;
jamie@104 620 }
jamie@104 621
jamie@104 622 /* be wary of these interpolated values */
jamie@140 623 for(n = order + 1; n <= cep_length; n++)
jamie@140 624 {
jamie@146 625 sum = 0.0;
jamie@104 626 for (k = n - (order - 1); k < n; k++)
jamie@104 627 sum += k * result[k-1] * data[n - k];
jamie@104 628 result[n-1] = sum / n;
jamie@104 629 }
jamie@104 630
jamie@104 631 return XTRACT_SUCCESS;
jamie@104 632
jamie@104 633 }
jamie@146 634 //int xtract_lpcc_s(const double *data, const int N, const void *argv, double *result){
jamie@104 635 // return XTRACT_SUCCESS;
jamie@104 636 //}
jamie@104 637
jamie@146 638 int xtract_subbands(const double *data, const int N, const void *argv, double *result)
jamie@140 639 {
jamie@104 640
jamie@114 641 int n, bw, xtract_func, nbands, scale, start, lower, *argi, rv;
jamie@114 642
jamie@114 643 argi = (int *)argv;
jamie@114 644
jamie@114 645 xtract_func = argi[0];
jamie@114 646 nbands = argi[1];
jamie@114 647 scale = argi[2];
jamie@114 648 start = argi[3];
jamie@114 649
jamie@114 650 if(scale == XTRACT_LINEAR_SUBBANDS)
jamie@114 651 bw = floorf((N - start) / nbands);
jamie@114 652 else
jamie@114 653 bw = start;
jamie@114 654
jamie@114 655 lower = start;
jamie@115 656 rv = XTRACT_SUCCESS;
jamie@114 657
jamie@140 658 for(n = 0; n < nbands; n++)
jamie@140 659 {
jamie@114 660
jamie@114 661 /* Bounds sanity check */
jamie@140 662 if(lower >= N || lower + bw >= N)
jamie@140 663 {
jamie@120 664 // printf("n: %d\n", n);
jamie@146 665 result[n] = 0.0;
jamie@114 666 continue;
jamie@115 667 }
jamie@114 668
jamie@114 669 rv = xtract[xtract_func](data+lower, bw, NULL, &result[n]);
jamie@114 670
jamie@114 671 if(rv != XTRACT_SUCCESS)
jamie@114 672 return rv;
jamie@114 673
jamie@140 674 switch(scale)
jamie@140 675 {
jamie@140 676 case XTRACT_OCTAVE_SUBBANDS:
jamie@140 677 lower += bw;
jamie@140 678 bw = lower;
jamie@140 679 break;
jamie@140 680 case XTRACT_LINEAR_SUBBANDS:
jamie@140 681 lower += bw;
jamie@140 682 break;
jamie@114 683 }
jamie@114 684
jamie@114 685 }
jamie@114 686
jamie@114 687 return rv;
jamie@114 688
jamie@114 689 }
jamie@114 690
jamie@114 691
jamie@114 692