annotate src/vector.c @ 154:826eb46b2f91

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