annotate src/vector.c @ 285:89fe52066db1 tip master

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