annotate src/scalar.c @ 192:bb60691d9570

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