annotate src/scalar.c @ 195:e63fa5ad1902

Include float.h on platforms that don't have DBL_MAX defined in limits.h
author Jamie Bullock <jamie@jamiebullock.com>
date Wed, 12 Feb 2014 08:36:58 +0000
parents bb60691d9570
children e764049c0a82
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
jamie@1 286 int n = N;
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 {
jamie@1 625
jamie@41 626 int n = N >> 1;
jamie@146 627 double num = 0.0, den = 0.0, fund;
jamie@146 628 const double *freqs, *amps;
jamie@1 629
jamie@146 630 fund = *(double *)argv;
jamie@52 631 amps = data;
jamie@52 632 freqs = data + n;
jamie@25 633
jamie@140 634 while(n--)
jamie@140 635 {
jamie@140 636 if(amps[n])
jamie@140 637 {
jamie@146 638 num += fabs(freqs[n] - n * 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 {
jamie@1 658
jamie@43 659 int M = (N >> 1), n;
jamie@1 660
jamie@146 661 double odd = 0.0, even = 0.0, temp;
jamie@44 662
jamie@140 663 for(n = 0; n < M; n++)
jamie@140 664 {
jamie@140 665 if((temp = data[n]))
jamie@140 666 {
jamie@140 667 if(XTRACT_IS_ODD(n))
jamie@140 668 {
jamie@140 669 odd += temp;
jamie@140 670 }
jamie@140 671 else
jamie@140 672 {
jamie@140 673 even += temp;
jamie@140 674 }
jamie@140 675 }
jamie@1 676 }
jamie@1 677
jamie@146 678 if(odd == 0.0 || even == 0.0)
jamie@140 679 {
jamie@146 680 *result = 0.0;
jamie@113 681 return XTRACT_NO_RESULT;
jamie@113 682 }
jamie@140 683 else
jamie@140 684 {
jamie@113 685 *result = odd / even;
jamie@113 686 return XTRACT_SUCCESS;
jamie@113 687 }
jamie@1 688 }
jamie@1 689
jamie@146 690 int xtract_sharpness(const double *data, const int N, const void *argv, double *result)
jamie@140 691 {
jamie@1 692
jamie@48 693 int n = N, rv;
jamie@146 694 double sl, g; /* sl = specific loudness */
jamie@140 695 double temp;
jamie@48 696
jamie@146 697 sl = g = 0.0;
jamie@146 698 temp = 0.0;
jamie@48 699
jamie@140 700 if(n > XTRACT_BARK_BANDS)
jamie@140 701 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 702 else
jamie@140 703 rv = XTRACT_SUCCESS;
jamie@48 704
jamie@48 705
jamie@140 706 while(n--)
jamie@140 707 {
jamie@146 708 sl = pow(data[n], 0.23);
jamie@146 709 g = (n < 15 ? 1.0 : 0.066 * exp(0.171 * n));
jamie@140 710 temp += n * g * sl;
jamie@48 711 }
jamie@48 712
jamie@146 713 temp = 0.11 * temp / (double)N;
jamie@146 714 *result = (double)temp;
jamie@48 715
jamie@48 716 return rv;
jamie@25 717
jamie@1 718 }
jamie@1 719
jamie@146 720 int xtract_spectral_slope(const double *data, const int N, const void *argv, double *result)
jamie@140 721 {
jamie@1 722
jamie@146 723 const double *freqs, *amps;
jamie@146 724 double f, a,
jamie@140 725 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@140 726 int n, M;
jamie@140 727
jamie@146 728 F = A = FA = FXTRACT_SQ = 0.0;
jamie@48 729 n = M = N >> 1;
jamie@48 730
jamie@52 731 amps = data;
jamie@52 732 freqs = data + n;
jamie@48 733
jamie@140 734 while(n--)
jamie@140 735 {
jamie@140 736 f = freqs[n];
jamie@140 737 a = amps[n];
jamie@140 738 F += f;
jamie@140 739 A += a;
jamie@140 740 FA += f * a;
jamie@140 741 FXTRACT_SQ += f * f;
jamie@48 742 }
jamie@48 743
jamie@146 744 *result = (1.0 / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 745
jamie@56 746 return XTRACT_SUCCESS;
jamie@25 747
jamie@1 748 }
jamie@1 749
jamie@146 750 int xtract_lowest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 751 {
jamie@25 752
jamie@45 753 int n = N;
jamie@45 754
jamie@192 755 *result = DBL_MAX;
jamie@45 756
jamie@140 757 while(n--)
jamie@140 758 {
jamie@192 759 if(data[n] > *(double *)argv)
jamie@140 760 *result = XTRACT_MIN(*result, data[n]);
jamie@45 761 }
jamie@45 762
jamie@192 763 if (*result == DBL_MAX)
jamie@192 764 return XTRACT_NO_RESULT;
jamie@192 765
jamie@56 766 return XTRACT_SUCCESS;
jamie@45 767 }
jamie@45 768
jamie@146 769 int xtract_highest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 770 {
jamie@45 771
jamie@1 772 int n = N;
jamie@1 773
jamie@46 774 *result = data[--n];
jamie@44 775
jamie@140 776 while(n--)
jamie@140 777 *result = XTRACT_MAX(*result, data[n]);
jamie@44 778
jamie@56 779 return XTRACT_SUCCESS;
jamie@1 780 }
jamie@1 781
jamie@45 782
jamie@146 783 int xtract_sum(const double *data, const int N, const void *argv, double *result)
jamie@140 784 {
jamie@45 785
jamie@45 786 int n = N;
jamie@45 787
jamie@146 788 *result = 0.0;
jamie@113 789
jamie@45 790 while(n--)
jamie@140 791 *result += *data++;
jamie@45 792
jamie@56 793 return XTRACT_SUCCESS;
jamie@45 794
jamie@45 795 }
jamie@45 796
jamie@146 797 int xtract_nonzero_count(const double *data, const int N, const void *argv, double *result)
jamie@140 798 {
jamie@59 799
jamie@59 800 int n = N;
jamie@140 801
jamie@146 802 *result = 0.0;
jamie@59 803
jamie@59 804 while(n--)
jamie@140 805 *result += (*data++ ? 1 : 0);
jamie@59 806
jamie@59 807 return XTRACT_SUCCESS;
jamie@59 808
jamie@59 809 }
jamie@59 810
jamie@146 811 int xtract_hps(const double *data, const int N, const void *argv, double *result)
jamie@140 812 {
jamie@1 813
jamie@1 814 int n = N, M, m, l, peak_index, position1_lwr;
jamie@146 815 double *coeffs2, *coeffs3, *product, L,
jamie@140 816 largest1_lwr, peak, ratio1, sr;
jamie@1 817
jamie@146 818 sr = *(double*)argv;
jamie@78 819 if(sr == 0)
jamie@146 820 sr = 44100.0;
jamie@25 821
jamie@146 822 coeffs2 = (double *)malloc(N * sizeof(double));
jamie@146 823 coeffs3 = (double *)malloc(N * sizeof(double));
jamie@146 824 product = (double *)malloc(N * sizeof(double));
jamie@25 825
jamie@1 826 while(n--) coeffs2[n] = coeffs3[n] = 1;
jamie@1 827
jamie@1 828 M = N >> 1;
jamie@146 829 L = N / 3.0;
jamie@1 830
jamie@140 831 while(M--)
jamie@140 832 {
jamie@140 833 m = M << 1;
jamie@146 834 coeffs2[M] = (data[m] + data[m+1]) * 0.5;
jamie@1 835
jamie@140 836 if(M < L)
jamie@140 837 {
jamie@140 838 l = M * 3;
jamie@146 839 coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3.0;
jamie@140 840 }
jamie@1 841 }
jamie@25 842
jamie@1 843 peak_index = peak = 0;
jamie@25 844
jamie@140 845 for(n = 1; n < N; n++)
jamie@140 846 {
jamie@140 847 product[n] = data[n] * coeffs2[n] * coeffs3[n];
jamie@140 848 if(product[n] > peak)
jamie@140 849 {
jamie@140 850 peak_index = n;
jamie@140 851 peak = product[n];
jamie@140 852 }
jamie@1 853 }
jamie@1 854
jamie@1 855 largest1_lwr = position1_lwr = 0;
jamie@1 856
jamie@140 857 for(n = 0; n < N; n++)
jamie@140 858 {
jamie@140 859 if(data[n] > largest1_lwr && n != peak_index)
jamie@140 860 {
jamie@140 861 largest1_lwr = data[n];
jamie@140 862 position1_lwr = n;
jamie@140 863 }
jamie@1 864 }
jamie@1 865
jamie@1 866 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 867
jamie@140 868 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@140 869 peak_index * 0.6 && ratio1 > 0.1)
jamie@140 870 peak_index = position1_lwr;
jamie@1 871
jamie@146 872 *result = sr / (double)peak_index;
jamie@25 873
jamie@1 874 free(coeffs2);
jamie@1 875 free(coeffs3);
jamie@1 876 free(product);
jamie@25 877
jamie@56 878 return XTRACT_SUCCESS;
jamie@1 879 }
jamie@5 880
jamie@5 881
jamie@146 882 int xtract_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 883 {
jamie@5 884
jamie@78 885 int M, tau, n;
jamie@146 886 double sr;
jamie@43 887 size_t bytes;
jamie@146 888 double f0, err_tau_1, err_tau_x, array_max,
jamie@140 889 threshold_peak, threshold_centre,
jamie@140 890 *input;
jamie@22 891
jamie@146 892 sr = *(double *)argv;
jamie@78 893 if(sr == 0)
jamie@146 894 sr = 44100.0;
jamie@43 895
jamie@146 896 input = (double *)malloc(bytes = N * sizeof(double));
jamie@43 897 input = memcpy(input, data, bytes);
jamie@146 898 /* threshold_peak = *((double *)argv+1);
jamie@146 899 threshold_centre = *((double *)argv+2);
jamie@146 900 printf("peak: %.2\tcentre: %.2\n", threshold_peak, threshold_centre);*/
jamie@25 901 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 902
jamie@25 903 /* FIX: tweak and make into macros */
jamie@25 904 threshold_peak = .8;
jamie@25 905 threshold_centre = .3;
jamie@25 906 M = N >> 1;
jamie@25 907 err_tau_1 = 0;
jamie@25 908 array_max = 0;
jamie@25 909
jamie@25 910 /* Find the array max */
jamie@140 911 for(n = 0; n < N; n++)
jamie@140 912 {
jamie@140 913 if (input[n] > array_max)
jamie@140 914 array_max = input[n];
jamie@12 915 }
jamie@25 916
jamie@25 917 threshold_peak *= array_max;
jamie@25 918
jamie@25 919 /* peak clip */
jamie@140 920 for(n = 0; n < N; n++)
jamie@140 921 {
jamie@140 922 if(input[n] > threshold_peak)
jamie@140 923 input[n] = threshold_peak;
jamie@140 924 else if(input[n] < -threshold_peak)
jamie@140 925 input[n] = -threshold_peak;
jamie@25 926 }
jamie@25 927
jamie@25 928 threshold_centre *= array_max;
jamie@25 929
jamie@25 930 /* Centre clip */
jamie@140 931 for(n = 0; n < N; n++)
jamie@140 932 {
jamie@140 933 if (input[n] < threshold_centre)
jamie@140 934 input[n] = 0;
jamie@140 935 else
jamie@140 936 input[n] -= threshold_centre;
jamie@25 937 }
jamie@25 938
jamie@25 939 /* Estimate fundamental freq */
jamie@25 940 for (n = 1; n < M; n++)
jamie@146 941 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@140 942 /* 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 943 for (tau = 2; tau < M; tau++)
jamie@140 944 {
jamie@140 945 err_tau_x = 0;
jamie@140 946 for (n = 1; n < M; n++)
jamie@140 947 {
jamie@146 948 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@140 949 }
jamie@140 950 if (err_tau_x < err_tau_1)
jamie@140 951 {
jamie@140 952 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@140 953 *result = f0;
jamie@140 954 free(input);
jamie@140 955 return XTRACT_SUCCESS;
jamie@140 956 }
jamie@25 957 }
jamie@43 958 *result = -0;
jamie@43 959 free(input);
jamie@56 960 return XTRACT_NO_RESULT;
jamie@5 961 }
jamie@43 962
jamie@146 963 int xtract_failsafe_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 964 {
jamie@44 965
jamie@146 966 double *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 967
jamie@43 968 return_code = xtract_f0(data, N, argv, result);
jamie@44 969
jamie@140 970 if(return_code == XTRACT_NO_RESULT)
jamie@140 971 {
jamie@146 972 sr = *(double *)argv;
jamie@140 973 if(sr == 0)
jamie@146 974 sr = 44100.0;
jamie@146 975 spectrum = (double *)malloc(N * sizeof(double));
jamie@146 976 peaks = (double *)malloc(N * sizeof(double));
jamie@140 977 argf[0] = sr;
jamie@140 978 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@140 979 xtract_spectrum(data, N, argf, spectrum);
jamie@146 980 argf[1] = 10.0;
jamie@140 981 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@146 982 argf[0] = 0.0;
jamie@140 983 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 984
jamie@140 985 free(spectrum);
jamie@140 986 free(peaks);
jamie@43 987 }
jamie@43 988
jamie@56 989 return XTRACT_SUCCESS;
jamie@43 990
jamie@43 991 }
jamie@44 992
jamie@161 993 int xtract_wavelet_f0(const double *data, const int N, const void *argv, double *result)
jamie@161 994 {
jamie@169 995 /* double sr = *(double *)argv; */
jamie@161 996
jamie@161 997 *result = dywapitch_computepitch(&wavelet_f0_state, data, 0, N);
jamie@161 998
jamie@161 999 if (*result == 0.0)
jamie@161 1000 {
jamie@161 1001 return XTRACT_NO_RESULT;
jamie@161 1002 }
jamie@161 1003
jamie@161 1004 return XTRACT_SUCCESS;
jamie@161 1005 }
jamie@161 1006
jamie@161 1007