annotate src/scalar.c @ 225:62e797c2974a

correction to xtract_odd_even_ratio
author Sean Enderby <sean.enderby@gmail.com>
date Mon, 24 Feb 2014 14:32:04 +0000
parents fdbef1474be9
children cabf2f465d1b
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@107 24 /* scalar.c: defines functions that extract a feature as a single value from an input vector */
jamie@1 25
jamie@5 26 #include <stdlib.h>
jamie@43 27 #include <string.h>
jamie@78 28 #include <stdio.h>
jamie@113 29 #include <math.h>
jamie@192 30 #include <limits.h>
jamie@113 31
jamie@195 32 #ifndef DBL_MAX
jamie@195 33 #include <float.h> /* on Linux DBL_MAX is in float.h */
jamie@195 34 #endif
jamie@195 35
jamie@161 36 #include "dywapitchtrack/dywapitchtrack.h"
jamie@161 37
jamie@163 38 #include "../xtract/libxtract.h"
jamie@163 39 #include "../xtract/xtract_helper.h"
jamie@113 40 #include "xtract_macros_private.h"
jamie@161 41 #include "xtract_globals_private.h"
jamie@1 42
jamie@146 43 int xtract_mean(const double *data, const int N, const void *argv, double *result)
jamie@140 44 {
jamie@25 45
jamie@1 46 int n = N;
jamie@1 47
jamie@146 48 *result = 0.0;
jamie@113 49
jamie@1 50 while(n--)
jamie@140 51 *result += data[n];
jamie@140 52
jamie@140 53 *result /= N;
jamie@140 54
jamie@140 55 return XTRACT_SUCCESS;
jamie@140 56 }
jamie@140 57
jamie@146 58 int xtract_variance(const double *data, const int N, const void *argv, double *result)
jamie@140 59 {
jamie@140 60
jamie@140 61 int n = N;
jamie@140 62
jamie@146 63 *result = 0.0;
jamie@140 64
jamie@140 65 while(n--)
jamie@146 66 *result += pow(data[n] - *(double *)argv, 2);
jamie@25 67
jamie@43 68 *result = *result / (N - 1);
jamie@44 69
jamie@56 70 return XTRACT_SUCCESS;
jamie@1 71 }
jamie@1 72
jamie@146 73 int xtract_standard_deviation(const double *data, const int N, const void *argv, double *result)
jamie@140 74 {
jamie@25 75
jamie@146 76 *result = sqrt(*(double *)argv);
jamie@25 77
jamie@56 78 return XTRACT_SUCCESS;
jamie@1 79 }
jamie@1 80
jamie@146 81 int xtract_average_deviation(const double *data, const int N, const void *argv, double *result)
jamie@140 82 {
jamie@25 83
jamie@1 84 int n = N;
jamie@44 85
jamie@146 86 *result = 0.0;
jamie@113 87
jamie@1 88 while(n--)
jamie@146 89 *result += fabs(data[n] - *(double *)argv);
jamie@25 90
jamie@1 91 *result /= N;
jamie@1 92
jamie@56 93 return XTRACT_SUCCESS;
jamie@1 94 }
jamie@1 95
jamie@146 96 int xtract_skewness(const double *data, const int N, const void *argv, double *result)
jamie@140 97 {
jamie@25 98
jamie@1 99 int n = N;
jamie@1 100
jamie@146 101 double temp = 0.0;
jamie@25 102
jamie@146 103 *result = 0.0;
jamie@113 104
jamie@140 105 while(n--)
jamie@140 106 {
jamie@146 107 temp = (data[n] - ((double *)argv)[0]) / ((double *)argv)[1];
jamie@146 108 *result += pow(temp, 3);
jamie@42 109 }
jamie@1 110
jamie@42 111 *result /= N;
jamie@44 112
jamie@59 113
jamie@56 114 return XTRACT_SUCCESS;
jamie@1 115 }
jamie@1 116
jamie@146 117 int xtract_kurtosis(const double *data, const int N, const void *argv, double *result)
jamie@140 118 {
jamie@25 119
jamie@1 120 int n = N;
jamie@1 121
jamie@146 122 double temp = 0.0;
jamie@113 123
jamie@146 124 *result = 0.0;
jamie@25 125
jamie@140 126 while(n--)
jamie@140 127 {
jamie@146 128 temp = (data[n] - ((double *)argv)[0]) / ((double *)argv)[1];
jamie@146 129 *result += pow(temp, 4);
jamie@42 130 }
jamie@25 131
jamie@42 132 *result /= N;
jamie@146 133 *result -= 3.0;
jamie@44 134
jamie@56 135 return XTRACT_SUCCESS;
jamie@1 136 }
jamie@1 137
jamie@146 138 int xtract_spectral_centroid(const double *data, const int N, const void *argv, double *result)
jamie@140 139 {
jamie@25 140
jamie@37 141 int n = (N >> 1);
jamie@11 142
jamie@146 143 const double *freqs, *amps;
jamie@146 144 double FA = 0.0, A = 0.0;
jamie@11 145
jamie@52 146 amps = data;
jamie@52 147 freqs = data + n;
jamie@25 148
jamie@140 149 while(n--)
jamie@140 150 {
jamie@140 151 FA += freqs[n] * amps[n];
jamie@140 152 A += amps[n];
jamie@25 153 }
jamie@25 154
jamie@146 155 if(A == 0.0)
jamie@146 156 *result = 0.0;
jamie@113 157 else
jamie@113 158 *result = FA / A;
jamie@11 159
jamie@56 160 return XTRACT_SUCCESS;
jamie@11 161 }
jamie@11 162
jamie@146 163 int xtract_spectral_mean(const double *data, const int N, const void *argv, double *result)
jamie@140 164 {
jamie@52 165
jamie@52 166 return xtract_spectral_centroid(data, N, argv, result);
jamie@52 167
jamie@52 168 }
jamie@52 169
jamie@146 170 int xtract_spectral_variance(const double *data, const int N, const void *argv, double *result)
jamie@140 171 {
jamie@52 172
jamie@53 173 int m;
jamie@146 174 double A = 0.0;
jamie@146 175 const double *freqs, *amps;
jamie@52 176
jamie@53 177 m = N >> 1;
jamie@52 178
jamie@53 179 amps = data;
jamie@53 180 freqs = data + m;
jamie@52 181
jamie@146 182 *result = 0.0;
jamie@113 183
jamie@140 184 while(m--)
jamie@140 185 {
jamie@123 186 A += amps[m];
jamie@146 187 *result += pow(freqs[m] - ((double *)argv)[0], 2) * amps[m];
jamie@53 188 }
jamie@53 189
jamie@123 190 *result = *result / A;
jamie@52 191
jamie@56 192 return XTRACT_SUCCESS;
jamie@52 193 }
jamie@52 194
jamie@146 195 int xtract_spectral_standard_deviation(const double *data, const int N, const void *argv, double *result)
jamie@140 196 {
jamie@52 197
jamie@146 198 *result = sqrt(*(double *)argv);
jamie@52 199
jamie@56 200 return XTRACT_SUCCESS;
jamie@52 201 }
jamie@52 202
jamie@146 203 /*int xtract_spectral_average_deviation(const double *data, const int N, const void *argv, double *result){
jamie@52 204
jamie@53 205 int m;
jamie@146 206 double A = 0.0;
jamie@146 207 const double *freqs, *amps;
jamie@52 208
jamie@53 209 m = N >> 1;
jamie@52 210
jamie@53 211 amps = data;
jamie@53 212 freqs = data + m;
jamie@52 213
jamie@146 214 *result = 0.0;
jamie@113 215
jamie@53 216 while(m--){
jamie@123 217 A += amps[m];
jamie@146 218 *result += fabs((amps[m] * freqs[m]) - *(double *)argv);
jamie@53 219 }
jamie@53 220
jamie@53 221 *result /= A;
jamie@52 222
jamie@56 223 return XTRACT_SUCCESS;
jamie@123 224 }*/
jamie@52 225
jamie@146 226 int xtract_spectral_skewness(const double *data, const int N, const void *argv, double *result)
jamie@140 227 {
jamie@52 228
jamie@53 229 int m;
jamie@146 230 const double *freqs, *amps;
jamie@52 231
jamie@53 232 m = N >> 1;
jamie@53 233
jamie@53 234 amps = data;
jamie@53 235 freqs = data + m;
jamie@52 236
jamie@146 237 *result = 0.0;
jamie@113 238
jamie@123 239 while(m--)
jamie@146 240 *result += pow(freqs[m] - ((double *)argv)[0], 3) * amps[m];
jamie@52 241
jamie@146 242 *result /= pow(((double *)argv)[1], 3);
jamie@52 243
jamie@56 244 return XTRACT_SUCCESS;
jamie@52 245 }
jamie@52 246
jamie@146 247 int xtract_spectral_kurtosis(const double *data, const int N, const void *argv, double *result)
jamie@140 248 {
jamie@52 249
jamie@53 250 int m;
jamie@146 251 const double *freqs, *amps;
jamie@52 252
jamie@53 253 m = N >> 1;
jamie@53 254
jamie@53 255 amps = data;
jamie@53 256 freqs = data + m;
jamie@52 257
jamie@146 258 *result = 0.0;
jamie@113 259
jamie@123 260 while(m--)
jamie@146 261 *result += pow(freqs[m] - ((double *)argv)[0], 4) * amps[m];
jamie@52 262
jamie@146 263 *result /= pow(((double *)argv)[1], 4);
jamie@146 264 *result -= 3.0;
jamie@52 265
jamie@56 266 return XTRACT_SUCCESS;
jamie@52 267 }
jamie@52 268
jamie@146 269 int xtract_irregularity_k(const double *data, const int N, const void *argv, double *result)
jamie@140 270 {
jamie@25 271
jamie@1 272 int n,
jamie@140 273 M = N - 1;
jamie@140 274
jamie@146 275 *result = 0.0;
jamie@140 276
jamie@1 277 for(n = 1; n < M; n++)
jamie@146 278 *result += fabs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3.0);
jamie@1 279
jamie@56 280 return XTRACT_SUCCESS;
jamie@1 281 }
jamie@1 282
jamie@146 283 int xtract_irregularity_j(const double *data, const int N, const void *argv, double *result)
jamie@140 284 {
jamie@25 285
sean@196 286 int n = N - 1;
jamie@1 287
jamie@146 288 double num = 0.0, den = 0.0;
jamie@1 289
jamie@140 290 while(n--)
jamie@140 291 {
jamie@146 292 num += pow(data[n] - data[n+1], 2);
jamie@146 293 den += pow(data[n], 2);
jamie@1 294 }
jamie@25 295
jamie@146 296 *result = (double)(num / den);
jamie@1 297
jamie@56 298 return XTRACT_SUCCESS;
jamie@1 299 }
jamie@1 300
jamie@146 301 int xtract_tristimulus_1(const double *data, const int N, const void *argv, double *result)
jamie@140 302 {
jamie@1 303
jamie@1 304 int n = N;
jamie@1 305
jamie@146 306 double den, p1, temp;
jamie@1 307
jamie@146 308 den = p1 = temp = 0.0;
jamie@1 309
jamie@140 310 for(n = 0; n < N; n++)
jamie@140 311 {
jamie@140 312 if((temp = data[n]))
jamie@140 313 {
jamie@140 314 den += temp;
jamie@140 315 if(!p1)
jamie@140 316 p1 = temp;
jamie@140 317 }
jamie@42 318 }
jamie@42 319
jamie@146 320 if(den == 0.0 || p1 == 0.0)
jamie@140 321 {
jamie@146 322 *result = 0.0;
jamie@113 323 return XTRACT_NO_RESULT;
jamie@113 324 }
jamie@140 325 else
jamie@140 326 {
jamie@113 327 *result = p1 / den;
jamie@113 328 return XTRACT_SUCCESS;
jamie@113 329 }
jamie@1 330 }
jamie@1 331
jamie@146 332 int xtract_tristimulus_2(const double *data, const int N, const void *argv, double *result)
jamie@140 333 {
jamie@25 334
jamie@1 335 int n = N;
jamie@1 336
jamie@146 337 double den, p2, p3, p4, ps, temp;
jamie@1 338
jamie@146 339 den = p2 = p3 = p4 = ps = temp = 0.0;
jamie@1 340
jamie@140 341 for(n = 0; n < N; n++)
jamie@140 342 {
jamie@140 343 if((temp = data[n]))
jamie@140 344 {
jamie@140 345 den += temp;
jamie@140 346 if(!p2)
jamie@140 347 p2 = temp;
jamie@140 348 else if(!p3)
jamie@140 349 p3 = temp;
jamie@140 350 else if(!p4)
jamie@140 351 p4 = temp;
jamie@140 352 }
jamie@42 353 }
jamie@42 354
jamie@113 355 ps = p2 + p3 + p4;
jamie@25 356
jamie@146 357 if(den == 0.0 || ps == 0.0)
jamie@140 358 {
jamie@146 359 *result = 0.0;
jamie@113 360 return XTRACT_NO_RESULT;
jamie@113 361 }
jamie@140 362 else
jamie@140 363 {
jamie@113 364 *result = ps / den;
jamie@113 365 return XTRACT_SUCCESS;
jamie@113 366 }
jamie@113 367
jamie@1 368 }
jamie@1 369
jamie@146 370 int xtract_tristimulus_3(const double *data, const int N, const void *argv, double *result)
jamie@140 371 {
jamie@25 372
jamie@42 373 int n = N, count = 0;
jamie@1 374
jamie@146 375 double den, num, temp;
jamie@1 376
jamie@146 377 den = num = temp = 0.0;
jamie@1 378
jamie@140 379 for(n = 0; n < N; n++)
jamie@140 380 {
jamie@140 381 if((temp = data[n]))
jamie@140 382 {
jamie@140 383 den += temp;
jamie@140 384 if(count >= 5)
jamie@140 385 num += temp;
jamie@140 386 count++;
jamie@140 387 }
jamie@42 388 }
jamie@25 389
jamie@146 390 if(den == 0.0 || num == 0.0)
jamie@140 391 {
jamie@146 392 *result = 0.0;
jamie@113 393 return XTRACT_NO_RESULT;
jamie@113 394 }
jamie@140 395 else
jamie@140 396 {
jamie@113 397 *result = num / den;
jamie@113 398 return XTRACT_SUCCESS;
jamie@113 399 }
jamie@1 400 }
jamie@1 401
jamie@146 402 int xtract_smoothness(const double *data, const int N, const void *argv, double *result)
jamie@140 403 {
jamie@25 404
jamie@184 405 int n;
jamie@184 406 int M = N - 1;
jamie@184 407 double prev = 0.0;
jamie@184 408 double current = 0.0;
jamie@184 409 double next = 0.0;
jamie@184 410 double temp = 0.0;
jamie@1 411
jamie@184 412
jamie@59 413
jamie@140 414 for(n = 1; n < M; n++)
jamie@140 415 {
jamie@184 416 if(n == 1)
jamie@184 417 {
jamie@184 418 prev = data[n-1] <= 0 ? XTRACT_LOG_LIMIT : data[n-1];
jamie@184 419 current = data[n] <= 0 ? XTRACT_LOG_LIMIT : data[n];
jamie@184 420 }
jamie@184 421 else
jamie@184 422 {
jamie@184 423 prev = current;
jamie@184 424 current = next;
jamie@184 425 }
jamie@184 426
jamie@184 427 next = data[n+1] <= 0 ? XTRACT_LOG_LIMIT : data[n+1];
jamie@184 428
jamie@184 429 temp += fabs(20.0 * log(current) - (20.0 * log(prev) +
jamie@184 430 20.0 * log(current) + 20.0 * log(next)) / 3.0);
jamie@25 431 }
jamie@184 432
jamie@184 433 *result = temp;
jamie@44 434
jamie@56 435 return XTRACT_SUCCESS;
jamie@1 436 }
jamie@1 437
jamie@146 438 int xtract_spread(const double *data, const int N, const void *argv, double *result)
jamie@140 439 {
jamie@1 440
jamie@140 441 return xtract_spectral_variance(data, N, argv, result);
jamie@1 442 }
jamie@1 443
jamie@146 444 int xtract_zcr(const double *data, const int N, const void *argv, double *result)
jamie@140 445 {
jamie@1 446
jamie@1 447 int n = N;
jamie@25 448
jamie@1 449 for(n = 1; n < N; n++)
jamie@140 450 if(data[n] * data[n-1] < 0) (*result)++;
jamie@25 451
jamie@146 452 *result /= (double)N;
jamie@25 453
jamie@56 454 return XTRACT_SUCCESS;
jamie@1 455 }
jamie@1 456
jamie@146 457 int xtract_rolloff(const double *data, const int N, const void *argv, double *result)
jamie@140 458 {
jamie@1 459
jamie@1 460 int n = N;
jamie@146 461 double pivot, temp, percentile;
jamie@42 462
jamie@146 463 pivot = temp = 0.0;
jamie@146 464 percentile = ((double *)argv)[1];
jamie@25 465
jamie@140 466 while(n--) pivot += data[n];
jamie@25 467
jamie@146 468 pivot *= percentile / 100.0;
jamie@25 469
jamie@42 470 for(n = 0; temp < pivot; n++)
jamie@140 471 temp += data[n];
jamie@1 472
jamie@146 473 *result = n * ((double *)argv)[0];
jamie@146 474 /* *result = (n / (double)N) * (((double *)argv)[1] * .5); */
jamie@25 475
jamie@56 476 return XTRACT_SUCCESS;
jamie@1 477 }
jamie@1 478
jamie@146 479 int xtract_loudness(const double *data, const int N, const void *argv, double *result)
jamie@140 480 {
jamie@25 481
jamie@47 482 int n = N, rv;
jamie@25 483
jamie@146 484 *result = 0.0;
jamie@113 485
jamie@140 486 if(n > XTRACT_BARK_BANDS)
jamie@140 487 {
jamie@140 488 n = XTRACT_BARK_BANDS;
jamie@140 489 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@93 490 }
jamie@47 491 else
jamie@140 492 rv = XTRACT_SUCCESS;
jamie@1 493
jamie@1 494 while(n--)
jamie@146 495 *result += pow(data[n], 0.23);
jamie@38 496
jamie@47 497 return rv;
jamie@1 498 }
jamie@1 499
jamie@146 500 int xtract_flatness(const double *data, const int N, const void *argv, double *result)
jamie@140 501 {
jamie@1 502
jamie@113 503 int n, count, denormal_found;
jamie@1 504
jamie@140 505 double num, den, temp;
jamie@25 506
jamie@146 507 num = 1.0;
jamie@146 508 den = temp = 0.0;
jamie@43 509
jamie@113 510 denormal_found = 0;
jamie@113 511 count = 0;
jamie@113 512
jamie@140 513 for(n = 0; n < N; n++)
jamie@140 514 {
jamie@146 515 if((temp = data[n]) != 0.0)
jamie@140 516 {
jamie@140 517 if (xtract_is_denormal(num))
jamie@140 518 {
jamie@113 519 denormal_found = 1;
jamie@113 520 break;
jamie@113 521 }
jamie@113 522 num *= temp;
jamie@113 523 den += temp;
jamie@113 524 count++;
jamie@113 525 }
jamie@1 526 }
jamie@44 527
jamie@140 528 if(!count)
jamie@140 529 {
jamie@146 530 *result = 0.0;
jamie@113 531 return XTRACT_NO_RESULT;
jamie@113 532 }
jamie@25 533
jamie@146 534 num = pow(num, 1.0 / (double)N);
jamie@146 535 den /= (double)N;
jamie@44 536
jamie@44 537
jamie@146 538 *result = (double) (num / den);
jamie@113 539
jamie@113 540 if(denormal_found)
jamie@113 541 return XTRACT_DENORMAL_FOUND;
jamie@113 542 else
jamie@113 543 return XTRACT_SUCCESS;
jamie@140 544
jamie@113 545 }
jamie@113 546
jamie@146 547 int xtract_flatness_db(const double *data, const int N, const void *argv, double *result)
jamie@140 548 {
jamie@113 549
jamie@146 550 double flatness;
jamie@113 551
jamie@146 552 flatness = *(double *)argv;
jamie@113 553
jamie@140 554 if (flatness <= 0)
jamie@115 555 flatness = XTRACT_LOG_LIMIT;
jamie@113 556
jamie@182 557 *result = 10 * log10(flatness);
jamie@25 558
jamie@56 559 return XTRACT_SUCCESS;
jamie@44 560
jamie@1 561 }
jamie@1 562
jamie@146 563 int xtract_tonality(const double *data, const int N, const void *argv, double *result)
jamie@140 564 {
jamie@25 565
jamie@146 566 double sfmdb;
jamie@25 567
jamie@146 568 sfmdb = *(double *)argv;
jamie@1 569
jamie@146 570 *result = XTRACT_MIN(sfmdb / -60.0, 1);
jamie@25 571
jamie@56 572 return XTRACT_SUCCESS;
jamie@1 573 }
jamie@1 574
jamie@146 575 int xtract_crest(const double *data, const int N, const void *argv, double *result)
jamie@140 576 {
jamie@25 577
jamie@146 578 double max, mean;
jamie@45 579
jamie@146 580 max = mean = 0.0;
jamie@45 581
jamie@146 582 max = *(double *)argv;
jamie@146 583 mean = *((double *)argv+1);
jamie@45 584
jamie@45 585 *result = max / mean;
jamie@45 586
jamie@56 587 return XTRACT_SUCCESS;
jamie@25 588
jamie@1 589 }
jamie@1 590
jamie@146 591 int xtract_noisiness(const double *data, const int N, const void *argv, double *result)
jamie@140 592 {
jamie@25 593
jamie@146 594 double h, i, p; /*harmonics, inharmonics, partials */
jamie@45 595
jamie@146 596 i = p = h = 0.0;
jamie@45 597
jamie@146 598 h = *(double *)argv;
jamie@146 599 p = *((double *)argv+1);
jamie@45 600
jamie@45 601 i = p - h;
jamie@45 602
jamie@45 603 *result = i / p;
jamie@45 604
jamie@56 605 return XTRACT_SUCCESS;
jamie@25 606
jamie@1 607 }
jamie@2 608
jamie@146 609 int xtract_rms_amplitude(const double *data, const int N, const void *argv, double *result)
jamie@140 610 {
jamie@1 611
jamie@1 612 int n = N;
jamie@1 613
jamie@146 614 *result = 0.0;
jamie@113 615
jamie@56 616 while(n--) *result += XTRACT_SQ(data[n]);
jamie@1 617
jamie@146 618 *result = sqrt(*result / (double)N);
jamie@25 619
jamie@56 620 return XTRACT_SUCCESS;
jamie@1 621 }
jamie@1 622
jamie@146 623 int xtract_spectral_inharmonicity(const double *data, const int N, const void *argv, double *result)
jamie@140 624 {
sean@223 625 int n = N >> 1, h = 0;
jamie@146 626 double num = 0.0, den = 0.0, fund;
jamie@146 627 const double *freqs, *amps;
jamie@1 628
jamie@146 629 fund = *(double *)argv;
jamie@52 630 amps = data;
jamie@52 631 freqs = data + n;
jamie@25 632
jamie@140 633 while(n--)
jamie@140 634 {
jamie@140 635 if(amps[n])
jamie@140 636 {
sean@223 637 h = round(freqs[n] / fund);
sean@223 638 num += fabs(freqs[n] - h * fund) * XTRACT_SQ(amps[n]);
jamie@140 639 den += XTRACT_SQ(amps[n]);
jamie@140 640 }
jamie@1 641 }
jamie@1 642
jamie@140 643 *result = (2 * num) / (fund * den);
jamie@25 644
jamie@56 645 return XTRACT_SUCCESS;
jamie@1 646 }
jamie@1 647
jamie@1 648
jamie@146 649 int xtract_power(const double *data, const int N, const void *argv, double *result)
jamie@140 650 {
jamie@1 651
jamie@56 652 return XTRACT_FEATURE_NOT_IMPLEMENTED;
jamie@25 653
jamie@1 654 }
jamie@1 655
jamie@146 656 int xtract_odd_even_ratio(const double *data, const int N, const void *argv, double *result)
jamie@140 657 {
sean@225 658 int n = N >> 1, h = 0;
sean@225 659 double odd = 0.0, even = 0.0, fund, temp;
sean@225 660 const double *freqs;
jamie@1 661
sean@225 662 fund = *(double *)argv;
sean@225 663 freqs = data + n;
jamie@1 664
sean@225 665 while(n--)
jamie@140 666 {
jamie@140 667 if((temp = data[n]))
jamie@140 668 {
sean@225 669 h = round(freqs[n] / fund);
sean@225 670 if(XTRACT_IS_ODD(h))
jamie@140 671 {
jamie@140 672 odd += temp;
jamie@140 673 }
jamie@140 674 else
jamie@140 675 {
jamie@140 676 even += temp;
jamie@140 677 }
jamie@140 678 }
jamie@1 679 }
jamie@1 680
jamie@146 681 if(odd == 0.0 || even == 0.0)
jamie@140 682 {
jamie@146 683 *result = 0.0;
jamie@113 684 return XTRACT_NO_RESULT;
jamie@113 685 }
jamie@140 686 else
jamie@140 687 {
jamie@113 688 *result = odd / even;
jamie@113 689 return XTRACT_SUCCESS;
jamie@113 690 }
jamie@1 691 }
jamie@1 692
jamie@146 693 int xtract_sharpness(const double *data, const int N, const void *argv, double *result)
jamie@140 694 {
jamie@1 695
jamie@48 696 int n = N, rv;
jamie@146 697 double sl, g; /* sl = specific loudness */
jamie@140 698 double temp;
jamie@48 699
jamie@146 700 sl = g = 0.0;
jamie@146 701 temp = 0.0;
jamie@48 702
jamie@140 703 if(n > XTRACT_BARK_BANDS)
jamie@140 704 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 705 else
jamie@140 706 rv = XTRACT_SUCCESS;
jamie@48 707
jamie@48 708
jamie@140 709 while(n--)
jamie@140 710 {
jamie@146 711 sl = pow(data[n], 0.23);
jamie@146 712 g = (n < 15 ? 1.0 : 0.066 * exp(0.171 * n));
jamie@140 713 temp += n * g * sl;
jamie@48 714 }
jamie@48 715
jamie@146 716 temp = 0.11 * temp / (double)N;
jamie@146 717 *result = (double)temp;
jamie@48 718
jamie@48 719 return rv;
jamie@25 720
jamie@1 721 }
jamie@1 722
jamie@146 723 int xtract_spectral_slope(const double *data, const int N, const void *argv, double *result)
jamie@140 724 {
jamie@1 725
jamie@146 726 const double *freqs, *amps;
jamie@146 727 double f, a,
jamie@140 728 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@140 729 int n, M;
jamie@140 730
jamie@146 731 F = A = FA = FXTRACT_SQ = 0.0;
jamie@48 732 n = M = N >> 1;
jamie@48 733
jamie@52 734 amps = data;
jamie@52 735 freqs = data + n;
jamie@48 736
jamie@140 737 while(n--)
jamie@140 738 {
jamie@140 739 f = freqs[n];
jamie@140 740 a = amps[n];
jamie@140 741 F += f;
jamie@140 742 A += a;
jamie@140 743 FA += f * a;
jamie@140 744 FXTRACT_SQ += f * f;
jamie@48 745 }
jamie@48 746
jamie@146 747 *result = (1.0 / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 748
jamie@56 749 return XTRACT_SUCCESS;
jamie@25 750
jamie@1 751 }
jamie@1 752
jamie@146 753 int xtract_lowest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 754 {
jamie@25 755
jamie@45 756 int n = N;
jamie@45 757
jamie@192 758 *result = DBL_MAX;
jamie@45 759
jamie@140 760 while(n--)
jamie@140 761 {
jamie@192 762 if(data[n] > *(double *)argv)
jamie@140 763 *result = XTRACT_MIN(*result, data[n]);
jamie@45 764 }
jamie@45 765
jamie@192 766 if (*result == DBL_MAX)
jamie@192 767 return XTRACT_NO_RESULT;
jamie@192 768
jamie@56 769 return XTRACT_SUCCESS;
jamie@45 770 }
jamie@45 771
jamie@146 772 int xtract_highest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 773 {
jamie@45 774
jamie@1 775 int n = N;
jamie@1 776
jamie@46 777 *result = data[--n];
jamie@44 778
jamie@140 779 while(n--)
jamie@140 780 *result = XTRACT_MAX(*result, data[n]);
jamie@44 781
jamie@56 782 return XTRACT_SUCCESS;
jamie@1 783 }
jamie@1 784
jamie@45 785
jamie@146 786 int xtract_sum(const double *data, const int N, const void *argv, double *result)
jamie@140 787 {
jamie@45 788
jamie@45 789 int n = N;
jamie@45 790
jamie@146 791 *result = 0.0;
jamie@113 792
jamie@45 793 while(n--)
jamie@140 794 *result += *data++;
jamie@45 795
jamie@56 796 return XTRACT_SUCCESS;
jamie@45 797
jamie@45 798 }
jamie@45 799
jamie@146 800 int xtract_nonzero_count(const double *data, const int N, const void *argv, double *result)
jamie@140 801 {
jamie@59 802
jamie@59 803 int n = N;
jamie@140 804
jamie@146 805 *result = 0.0;
jamie@59 806
jamie@59 807 while(n--)
jamie@140 808 *result += (*data++ ? 1 : 0);
jamie@59 809
jamie@59 810 return XTRACT_SUCCESS;
jamie@59 811
jamie@59 812 }
jamie@59 813
sean@198 814 int xtract_hps(const double *data, const int N, const void *argv, double *result)
jamie@140 815 {
sean@198 816 int n, M, i, peak_index, position1_lwr;
sean@198 817 double tempProduct, peak, largest1_lwr, ratio1;
jamie@1 818
sean@198 819 n = N / 2;
jamie@1 820
sean@198 821 M = ceil(n / 3.0);
jamie@25 822
sean@198 823 if (M <= 1)
jamie@140 824 {
sean@198 825 /* Input data is too short. */
sean@198 826 *result = 0;
sean@198 827 return XTRACT_NO_RESULT;
jamie@1 828 }
jamie@25 829
sean@198 830 tempProduct = peak = 0;
sean@198 831 for (i = 0; i < M; ++i)
sean@198 832 {
sean@198 833 tempProduct = data [i] * data [i * 2] * data [i * 3];
jamie@25 834
sean@198 835 if (tempProduct > peak)
jamie@140 836 {
sean@198 837 peak = tempProduct;
sean@198 838 peak_index = i;
jamie@140 839 }
jamie@1 840 }
jamie@1 841
jamie@1 842 largest1_lwr = position1_lwr = 0;
jamie@1 843
sean@198 844 for(i = 0; i < N; ++i)
jamie@140 845 {
sean@198 846 if(data[i] > largest1_lwr && i != peak_index)
jamie@140 847 {
sean@198 848 largest1_lwr = data[i];
sean@198 849 position1_lwr = i;
jamie@140 850 }
jamie@1 851 }
jamie@1 852
jamie@1 853 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 854
jamie@140 855 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@140 856 peak_index * 0.6 && ratio1 > 0.1)
jamie@140 857 peak_index = position1_lwr;
jamie@1 858
sean@198 859 *result = data [n + peak_index];
sean@196 860
sean@196 861 return XTRACT_SUCCESS;
jamie@1 862 }
jamie@5 863
jamie@146 864 int xtract_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 865 {
jamie@5 866
jamie@78 867 int M, tau, n;
jamie@146 868 double sr;
jamie@43 869 size_t bytes;
jamie@146 870 double f0, err_tau_1, err_tau_x, array_max,
jamie@140 871 threshold_peak, threshold_centre,
jamie@140 872 *input;
jamie@22 873
jamie@146 874 sr = *(double *)argv;
jamie@78 875 if(sr == 0)
jamie@146 876 sr = 44100.0;
jamie@43 877
jamie@146 878 input = (double *)malloc(bytes = N * sizeof(double));
jamie@43 879 input = memcpy(input, data, bytes);
jamie@146 880 /* threshold_peak = *((double *)argv+1);
jamie@146 881 threshold_centre = *((double *)argv+2);
jamie@146 882 printf("peak: %.2\tcentre: %.2\n", threshold_peak, threshold_centre);*/
jamie@25 883 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 884
jamie@25 885 /* FIX: tweak and make into macros */
jamie@25 886 threshold_peak = .8;
jamie@25 887 threshold_centre = .3;
jamie@25 888 M = N >> 1;
jamie@25 889 err_tau_1 = 0;
jamie@25 890 array_max = 0;
jamie@25 891
jamie@25 892 /* Find the array max */
jamie@140 893 for(n = 0; n < N; n++)
jamie@140 894 {
jamie@140 895 if (input[n] > array_max)
jamie@140 896 array_max = input[n];
jamie@12 897 }
jamie@25 898
jamie@25 899 threshold_peak *= array_max;
jamie@25 900
jamie@25 901 /* peak clip */
jamie@140 902 for(n = 0; n < N; n++)
jamie@140 903 {
jamie@140 904 if(input[n] > threshold_peak)
jamie@140 905 input[n] = threshold_peak;
jamie@140 906 else if(input[n] < -threshold_peak)
jamie@140 907 input[n] = -threshold_peak;
jamie@25 908 }
jamie@25 909
jamie@25 910 threshold_centre *= array_max;
jamie@25 911
jamie@25 912 /* Centre clip */
jamie@140 913 for(n = 0; n < N; n++)
jamie@140 914 {
jamie@140 915 if (input[n] < threshold_centre)
jamie@140 916 input[n] = 0;
jamie@140 917 else
jamie@140 918 input[n] -= threshold_centre;
jamie@25 919 }
jamie@25 920
jamie@25 921 /* Estimate fundamental freq */
jamie@25 922 for (n = 1; n < M; n++)
jamie@146 923 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@140 924 /* FIX: this doesn't pose too much load if it returns 'early', but if it can't find f0, load can be significant for larger block sizes M^2 iterations! */
jamie@140 925 for (tau = 2; tau < M; tau++)
jamie@140 926 {
jamie@140 927 err_tau_x = 0;
jamie@140 928 for (n = 1; n < M; n++)
jamie@140 929 {
jamie@146 930 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@140 931 }
jamie@140 932 if (err_tau_x < err_tau_1)
jamie@140 933 {
jamie@140 934 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@140 935 *result = f0;
jamie@140 936 free(input);
jamie@140 937 return XTRACT_SUCCESS;
jamie@140 938 }
jamie@25 939 }
jamie@43 940 *result = -0;
jamie@43 941 free(input);
jamie@56 942 return XTRACT_NO_RESULT;
jamie@5 943 }
jamie@43 944
jamie@146 945 int xtract_failsafe_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 946 {
jamie@44 947
jamie@146 948 double *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 949
jamie@43 950 return_code = xtract_f0(data, N, argv, result);
jamie@44 951
jamie@140 952 if(return_code == XTRACT_NO_RESULT)
jamie@140 953 {
jamie@146 954 sr = *(double *)argv;
jamie@140 955 if(sr == 0)
jamie@146 956 sr = 44100.0;
jamie@146 957 spectrum = (double *)malloc(N * sizeof(double));
jamie@146 958 peaks = (double *)malloc(N * sizeof(double));
jamie@140 959 argf[0] = sr;
jamie@140 960 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@140 961 xtract_spectrum(data, N, argf, spectrum);
jamie@146 962 argf[1] = 10.0;
jamie@140 963 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@146 964 argf[0] = 0.0;
jamie@140 965 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 966
jamie@140 967 free(spectrum);
jamie@140 968 free(peaks);
jamie@43 969 }
jamie@43 970
jamie@56 971 return XTRACT_SUCCESS;
jamie@43 972
jamie@43 973 }
jamie@44 974
jamie@161 975 int xtract_wavelet_f0(const double *data, const int N, const void *argv, double *result)
jamie@161 976 {
jamie@169 977 /* double sr = *(double *)argv; */
jamie@161 978
jamie@161 979 *result = dywapitch_computepitch(&wavelet_f0_state, data, 0, N);
jamie@161 980
jamie@161 981 if (*result == 0.0)
jamie@161 982 {
jamie@161 983 return XTRACT_NO_RESULT;
jamie@161 984 }
jamie@161 985
jamie@161 986 return XTRACT_SUCCESS;
jamie@161 987 }
jamie@161 988
jamie@161 989