annotate src/vector.c @ 171:661c1c732269

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