annotate src/scalar.c @ 229:a2f66a305e53

tristimulus3 correction
author Sean Enderby <sean.enderby@gmail.com>
date Tue, 25 Feb 2014 14:12:29 +0000
parents cccd314664ac
children b786a835df59
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
sean@227 301 /*
sean@227 302 *int xtract_tristimulus_1(const double *data, const int N, const void *argv, double *result)
sean@227 303 *{
sean@227 304 *
sean@227 305 * int n = N;
sean@227 306 *
sean@227 307 * double den, p1, temp;
sean@227 308 *
sean@227 309 * den = p1 = temp = 0.0;
sean@227 310 *
sean@227 311 * for(n = 0; n < N; n++)
sean@227 312 * {
sean@227 313 * if((temp = data[n]))
sean@227 314 * {
sean@227 315 * den += temp;
sean@227 316 * if(!p1)
sean@227 317 * p1 = temp;
sean@227 318 * }
sean@227 319 * }
sean@227 320 *
sean@227 321 * if(den == 0.0 || p1 == 0.0)
sean@227 322 * {
sean@227 323 * *result = 0.0;
sean@227 324 * return XTRACT_NO_RESULT;
sean@227 325 * }
sean@227 326 * else
sean@227 327 * {
sean@227 328 * *result = p1 / den;
sean@227 329 * return XTRACT_SUCCESS;
sean@227 330 * }
sean@227 331 *}
sean@227 332 *
sean@227 333 *int xtract_tristimulus_2(const double *data, const int N, const void *argv, double *result)
sean@227 334 *{
sean@227 335 *
sean@227 336 * int n = N;
sean@227 337 *
sean@227 338 * double den, p2, p3, p4, ps, temp;
sean@227 339 *
sean@227 340 * den = p2 = p3 = p4 = ps = temp = 0.0;
sean@227 341 *
sean@227 342 * for(n = 0; n < N; n++)
sean@227 343 * {
sean@227 344 * if((temp = data[n]))
sean@227 345 * {
sean@227 346 * den += temp;
sean@227 347 * if(!p2)
sean@227 348 * p2 = temp;
sean@227 349 * else if(!p3)
sean@227 350 * p3 = temp;
sean@227 351 * else if(!p4)
sean@227 352 * p4 = temp;
sean@227 353 * }
sean@227 354 * }
sean@227 355 *
sean@227 356 * ps = p2 + p3 + p4;
sean@227 357 *
sean@227 358 * if(den == 0.0 || ps == 0.0)
sean@227 359 * {
sean@227 360 * *result = 0.0;
sean@227 361 * return XTRACT_NO_RESULT;
sean@227 362 * }
sean@227 363 * else
sean@227 364 * {
sean@227 365 * *result = ps / den;
sean@227 366 * return XTRACT_SUCCESS;
sean@227 367 * }
sean@227 368 *
sean@227 369 *}
sean@227 370 *
sean@227 371 *int xtract_tristimulus_3(const double *data, const int N, const void *argv, double *result)
sean@227 372 *{
sean@227 373 *
sean@227 374 * int n = N, count = 0;
sean@227 375 *
sean@227 376 * double den, num, temp;
sean@227 377 *
sean@227 378 * den = num = temp = 0.0;
sean@227 379 *
sean@227 380 * for(n = 0; n < N; n++)
sean@227 381 * {
sean@227 382 * if((temp = data[n]))
sean@227 383 * {
sean@227 384 * den += temp;
sean@227 385 * if(count >= 5)
sean@227 386 * num += temp;
sean@227 387 * count++;
sean@227 388 * }
sean@227 389 * }
sean@227 390 *
sean@227 391 * if(den == 0.0 || num == 0.0)
sean@227 392 * {
sean@227 393 * *result = 0.0;
sean@227 394 * return XTRACT_NO_RESULT;
sean@227 395 * }
sean@227 396 * else
sean@227 397 * {
sean@227 398 * *result = num / den;
sean@227 399 * return XTRACT_SUCCESS;
sean@227 400 * }
sean@227 401 *}
sean@227 402 */
sean@227 403
jamie@146 404 int xtract_tristimulus_1(const double *data, const int N, const void *argv, double *result)
jamie@140 405 {
sean@227 406 int n = N >> 1, h = 0, i;
sean@227 407 double den = 0.0, p1 = 0.0, fund = 0.0, temp = 0.0;
sean@227 408 const double *freqs;
jamie@1 409
sean@227 410 fund = *(double *)argv;
sean@227 411 freqs = data + n;
jamie@1 412
sean@227 413 for(i = 0; i < n; i++)
jamie@140 414 {
sean@227 415 if((temp = data[i]))
jamie@140 416 {
jamie@140 417 den += temp;
sean@227 418 h = round(freqs[i] / fund);
sean@227 419 if(h == 1)
sean@227 420 p1 += temp;
jamie@140 421 }
jamie@42 422 }
jamie@42 423
jamie@146 424 if(den == 0.0 || p1 == 0.0)
jamie@140 425 {
jamie@146 426 *result = 0.0;
jamie@113 427 return XTRACT_NO_RESULT;
jamie@113 428 }
jamie@140 429 else
jamie@140 430 {
jamie@113 431 *result = p1 / den;
jamie@113 432 return XTRACT_SUCCESS;
jamie@113 433 }
jamie@1 434 }
jamie@1 435
jamie@146 436 int xtract_tristimulus_2(const double *data, const int N, const void *argv, double *result)
jamie@140 437 {
jamie@25 438
sean@228 439 int n = N >> 1, h = 0, i;
sean@228 440 double den, p2, p3, p4, ps, fund, temp;
sean@228 441 den = p2 = p3 = p4 = ps = fund = temp = 0.0;
sean@228 442 const double *freqs;
jamie@1 443
sean@228 444 fund = *(double *)argv;
sean@228 445 freqs = data + n;
jamie@1 446
sean@228 447 for(i = 0; i < n; i++)
jamie@140 448 {
sean@228 449 if((temp = data[i]))
jamie@140 450 {
jamie@140 451 den += temp;
sean@228 452 h = round(freqs[i] / fund);
sean@228 453 switch (h)
sean@228 454 {
sean@228 455 case 2:
sean@228 456 p2 += temp;
sean@228 457 break;
sean@228 458
sean@228 459 case 3:
sean@228 460 p3 += temp;
sean@228 461 break;
sean@228 462
sean@228 463 case 4:
sean@228 464 p4 += temp;
sean@228 465
sean@228 466 default:
sean@228 467 break;
sean@228 468 }
jamie@140 469 }
jamie@42 470 }
jamie@42 471
jamie@113 472 ps = p2 + p3 + p4;
jamie@25 473
jamie@146 474 if(den == 0.0 || ps == 0.0)
jamie@140 475 {
jamie@146 476 *result = 0.0;
jamie@113 477 return XTRACT_NO_RESULT;
jamie@113 478 }
jamie@140 479 else
jamie@140 480 {
jamie@113 481 *result = ps / den;
jamie@113 482 return XTRACT_SUCCESS;
jamie@113 483 }
jamie@113 484
jamie@1 485 }
jamie@1 486
jamie@146 487 int xtract_tristimulus_3(const double *data, const int N, const void *argv, double *result)
jamie@140 488 {
sean@229 489 int n = N >> 1, h = 0, i;
sean@229 490 double den = 0.0, num = 0.0, fund = 0.0, temp = 0.0;
sean@229 491 const double *freqs;
jamie@25 492
sean@229 493 fund = *(double *)argv;
sean@229 494 freqs = data + n;
jamie@1 495
sean@229 496 for(i = 0; i < n; i++)
jamie@140 497 {
sean@229 498 if((temp = data[i]))
jamie@140 499 {
jamie@140 500 den += temp;
sean@229 501 h = round(freqs[i] / fund);
sean@229 502 if(h >= 5)
jamie@140 503 num += temp;
jamie@140 504 }
jamie@42 505 }
jamie@25 506
jamie@146 507 if(den == 0.0 || num == 0.0)
jamie@140 508 {
jamie@146 509 *result = 0.0;
jamie@113 510 return XTRACT_NO_RESULT;
jamie@113 511 }
jamie@140 512 else
jamie@140 513 {
jamie@113 514 *result = num / den;
jamie@113 515 return XTRACT_SUCCESS;
jamie@113 516 }
jamie@1 517 }
jamie@1 518
jamie@146 519 int xtract_smoothness(const double *data, const int N, const void *argv, double *result)
jamie@140 520 {
jamie@25 521
jamie@184 522 int n;
jamie@184 523 int M = N - 1;
jamie@184 524 double prev = 0.0;
jamie@184 525 double current = 0.0;
jamie@184 526 double next = 0.0;
jamie@184 527 double temp = 0.0;
jamie@1 528
jamie@184 529
jamie@59 530
jamie@140 531 for(n = 1; n < M; n++)
jamie@140 532 {
jamie@184 533 if(n == 1)
jamie@184 534 {
jamie@184 535 prev = data[n-1] <= 0 ? XTRACT_LOG_LIMIT : data[n-1];
jamie@184 536 current = data[n] <= 0 ? XTRACT_LOG_LIMIT : data[n];
jamie@184 537 }
jamie@184 538 else
jamie@184 539 {
jamie@184 540 prev = current;
jamie@184 541 current = next;
jamie@184 542 }
jamie@184 543
jamie@184 544 next = data[n+1] <= 0 ? XTRACT_LOG_LIMIT : data[n+1];
jamie@184 545
jamie@184 546 temp += fabs(20.0 * log(current) - (20.0 * log(prev) +
jamie@184 547 20.0 * log(current) + 20.0 * log(next)) / 3.0);
jamie@25 548 }
jamie@184 549
jamie@184 550 *result = temp;
jamie@44 551
jamie@56 552 return XTRACT_SUCCESS;
jamie@1 553 }
jamie@1 554
jamie@146 555 int xtract_spread(const double *data, const int N, const void *argv, double *result)
jamie@140 556 {
jamie@1 557
jamie@140 558 return xtract_spectral_variance(data, N, argv, result);
jamie@1 559 }
jamie@1 560
jamie@146 561 int xtract_zcr(const double *data, const int N, const void *argv, double *result)
jamie@140 562 {
jamie@1 563
jamie@1 564 int n = N;
jamie@25 565
jamie@1 566 for(n = 1; n < N; n++)
jamie@140 567 if(data[n] * data[n-1] < 0) (*result)++;
jamie@25 568
jamie@146 569 *result /= (double)N;
jamie@25 570
jamie@56 571 return XTRACT_SUCCESS;
jamie@1 572 }
jamie@1 573
jamie@146 574 int xtract_rolloff(const double *data, const int N, const void *argv, double *result)
jamie@140 575 {
jamie@1 576
jamie@1 577 int n = N;
jamie@146 578 double pivot, temp, percentile;
jamie@42 579
jamie@146 580 pivot = temp = 0.0;
jamie@146 581 percentile = ((double *)argv)[1];
jamie@25 582
jamie@140 583 while(n--) pivot += data[n];
jamie@25 584
jamie@146 585 pivot *= percentile / 100.0;
jamie@25 586
jamie@42 587 for(n = 0; temp < pivot; n++)
jamie@140 588 temp += data[n];
jamie@1 589
jamie@146 590 *result = n * ((double *)argv)[0];
jamie@146 591 /* *result = (n / (double)N) * (((double *)argv)[1] * .5); */
jamie@25 592
jamie@56 593 return XTRACT_SUCCESS;
jamie@1 594 }
jamie@1 595
jamie@146 596 int xtract_loudness(const double *data, const int N, const void *argv, double *result)
jamie@140 597 {
jamie@25 598
jamie@47 599 int n = N, rv;
jamie@25 600
jamie@146 601 *result = 0.0;
jamie@113 602
jamie@140 603 if(n > XTRACT_BARK_BANDS)
jamie@140 604 {
jamie@140 605 n = XTRACT_BARK_BANDS;
jamie@140 606 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@93 607 }
jamie@47 608 else
jamie@140 609 rv = XTRACT_SUCCESS;
jamie@1 610
jamie@1 611 while(n--)
jamie@146 612 *result += pow(data[n], 0.23);
jamie@38 613
jamie@47 614 return rv;
jamie@1 615 }
jamie@1 616
jamie@146 617 int xtract_flatness(const double *data, const int N, const void *argv, double *result)
jamie@140 618 {
jamie@1 619
jamie@113 620 int n, count, denormal_found;
jamie@1 621
jamie@140 622 double num, den, temp;
jamie@25 623
jamie@146 624 num = 1.0;
jamie@146 625 den = temp = 0.0;
jamie@43 626
jamie@113 627 denormal_found = 0;
jamie@113 628 count = 0;
jamie@113 629
jamie@140 630 for(n = 0; n < N; n++)
jamie@140 631 {
jamie@146 632 if((temp = data[n]) != 0.0)
jamie@140 633 {
jamie@140 634 if (xtract_is_denormal(num))
jamie@140 635 {
jamie@113 636 denormal_found = 1;
jamie@113 637 break;
jamie@113 638 }
jamie@113 639 num *= temp;
jamie@113 640 den += temp;
jamie@113 641 count++;
jamie@113 642 }
jamie@1 643 }
jamie@44 644
jamie@140 645 if(!count)
jamie@140 646 {
jamie@146 647 *result = 0.0;
jamie@113 648 return XTRACT_NO_RESULT;
jamie@113 649 }
jamie@25 650
jamie@146 651 num = pow(num, 1.0 / (double)N);
jamie@146 652 den /= (double)N;
jamie@44 653
jamie@44 654
jamie@146 655 *result = (double) (num / den);
jamie@113 656
jamie@113 657 if(denormal_found)
jamie@113 658 return XTRACT_DENORMAL_FOUND;
jamie@113 659 else
jamie@113 660 return XTRACT_SUCCESS;
jamie@140 661
jamie@113 662 }
jamie@113 663
jamie@146 664 int xtract_flatness_db(const double *data, const int N, const void *argv, double *result)
jamie@140 665 {
jamie@113 666
jamie@146 667 double flatness;
jamie@113 668
jamie@146 669 flatness = *(double *)argv;
jamie@113 670
jamie@140 671 if (flatness <= 0)
jamie@115 672 flatness = XTRACT_LOG_LIMIT;
jamie@113 673
jamie@182 674 *result = 10 * log10(flatness);
jamie@25 675
jamie@56 676 return XTRACT_SUCCESS;
jamie@44 677
jamie@1 678 }
jamie@1 679
jamie@146 680 int xtract_tonality(const double *data, const int N, const void *argv, double *result)
jamie@140 681 {
jamie@25 682
jamie@146 683 double sfmdb;
jamie@25 684
jamie@146 685 sfmdb = *(double *)argv;
jamie@1 686
jamie@146 687 *result = XTRACT_MIN(sfmdb / -60.0, 1);
jamie@25 688
jamie@56 689 return XTRACT_SUCCESS;
jamie@1 690 }
jamie@1 691
jamie@146 692 int xtract_crest(const double *data, const int N, const void *argv, double *result)
jamie@140 693 {
jamie@25 694
jamie@146 695 double max, mean;
jamie@45 696
jamie@146 697 max = mean = 0.0;
jamie@45 698
jamie@146 699 max = *(double *)argv;
jamie@146 700 mean = *((double *)argv+1);
jamie@45 701
jamie@45 702 *result = max / mean;
jamie@45 703
jamie@56 704 return XTRACT_SUCCESS;
jamie@25 705
jamie@1 706 }
jamie@1 707
jamie@146 708 int xtract_noisiness(const double *data, const int N, const void *argv, double *result)
jamie@140 709 {
jamie@25 710
jamie@146 711 double h, i, p; /*harmonics, inharmonics, partials */
jamie@45 712
jamie@146 713 i = p = h = 0.0;
jamie@45 714
jamie@146 715 h = *(double *)argv;
jamie@146 716 p = *((double *)argv+1);
jamie@45 717
jamie@45 718 i = p - h;
jamie@45 719
jamie@45 720 *result = i / p;
jamie@45 721
jamie@56 722 return XTRACT_SUCCESS;
jamie@25 723
jamie@1 724 }
jamie@2 725
jamie@146 726 int xtract_rms_amplitude(const double *data, const int N, const void *argv, double *result)
jamie@140 727 {
jamie@1 728
jamie@1 729 int n = N;
jamie@1 730
jamie@146 731 *result = 0.0;
jamie@113 732
jamie@56 733 while(n--) *result += XTRACT_SQ(data[n]);
jamie@1 734
jamie@146 735 *result = sqrt(*result / (double)N);
jamie@25 736
jamie@56 737 return XTRACT_SUCCESS;
jamie@1 738 }
jamie@1 739
jamie@146 740 int xtract_spectral_inharmonicity(const double *data, const int N, const void *argv, double *result)
jamie@140 741 {
sean@223 742 int n = N >> 1, h = 0;
jamie@146 743 double num = 0.0, den = 0.0, fund;
jamie@146 744 const double *freqs, *amps;
jamie@1 745
jamie@146 746 fund = *(double *)argv;
jamie@52 747 amps = data;
jamie@52 748 freqs = data + n;
jamie@25 749
jamie@140 750 while(n--)
jamie@140 751 {
jamie@140 752 if(amps[n])
jamie@140 753 {
sean@223 754 h = round(freqs[n] / fund);
sean@223 755 num += fabs(freqs[n] - h * fund) * XTRACT_SQ(amps[n]);
jamie@140 756 den += XTRACT_SQ(amps[n]);
jamie@140 757 }
jamie@1 758 }
jamie@1 759
jamie@140 760 *result = (2 * num) / (fund * den);
jamie@25 761
jamie@56 762 return XTRACT_SUCCESS;
jamie@1 763 }
jamie@1 764
jamie@1 765
jamie@146 766 int xtract_power(const double *data, const int N, const void *argv, double *result)
jamie@140 767 {
jamie@1 768
jamie@56 769 return XTRACT_FEATURE_NOT_IMPLEMENTED;
jamie@25 770
jamie@1 771 }
jamie@1 772
jamie@146 773 int xtract_odd_even_ratio(const double *data, const int N, const void *argv, double *result)
jamie@140 774 {
sean@225 775 int n = N >> 1, h = 0;
sean@225 776 double odd = 0.0, even = 0.0, fund, temp;
sean@225 777 const double *freqs;
jamie@1 778
sean@225 779 fund = *(double *)argv;
sean@225 780 freqs = data + n;
jamie@1 781
sean@225 782 while(n--)
jamie@140 783 {
jamie@140 784 if((temp = data[n]))
jamie@140 785 {
sean@225 786 h = round(freqs[n] / fund);
sean@225 787 if(XTRACT_IS_ODD(h))
jamie@140 788 {
jamie@140 789 odd += temp;
jamie@140 790 }
jamie@140 791 else
jamie@140 792 {
jamie@140 793 even += temp;
jamie@140 794 }
jamie@140 795 }
jamie@1 796 }
jamie@1 797
jamie@146 798 if(odd == 0.0 || even == 0.0)
jamie@140 799 {
jamie@146 800 *result = 0.0;
jamie@113 801 return XTRACT_NO_RESULT;
jamie@113 802 }
jamie@140 803 else
jamie@140 804 {
jamie@113 805 *result = odd / even;
jamie@113 806 return XTRACT_SUCCESS;
jamie@113 807 }
jamie@1 808 }
jamie@1 809
jamie@146 810 int xtract_sharpness(const double *data, const int N, const void *argv, double *result)
jamie@140 811 {
jamie@1 812
jamie@48 813 int n = N, rv;
jamie@146 814 double sl, g; /* sl = specific loudness */
jamie@140 815 double temp;
jamie@48 816
jamie@146 817 sl = g = 0.0;
jamie@146 818 temp = 0.0;
jamie@48 819
jamie@140 820 if(n > XTRACT_BARK_BANDS)
jamie@140 821 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 822 else
jamie@140 823 rv = XTRACT_SUCCESS;
jamie@48 824
jamie@48 825
jamie@140 826 while(n--)
jamie@140 827 {
jamie@146 828 sl = pow(data[n], 0.23);
jamie@146 829 g = (n < 15 ? 1.0 : 0.066 * exp(0.171 * n));
jamie@140 830 temp += n * g * sl;
jamie@48 831 }
jamie@48 832
jamie@146 833 temp = 0.11 * temp / (double)N;
jamie@146 834 *result = (double)temp;
jamie@48 835
jamie@48 836 return rv;
jamie@25 837
jamie@1 838 }
jamie@1 839
jamie@146 840 int xtract_spectral_slope(const double *data, const int N, const void *argv, double *result)
jamie@140 841 {
jamie@1 842
jamie@146 843 const double *freqs, *amps;
jamie@146 844 double f, a,
jamie@140 845 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@140 846 int n, M;
jamie@140 847
jamie@146 848 F = A = FA = FXTRACT_SQ = 0.0;
jamie@48 849 n = M = N >> 1;
jamie@48 850
jamie@52 851 amps = data;
jamie@52 852 freqs = data + n;
jamie@48 853
jamie@140 854 while(n--)
jamie@140 855 {
jamie@140 856 f = freqs[n];
jamie@140 857 a = amps[n];
jamie@140 858 F += f;
jamie@140 859 A += a;
jamie@140 860 FA += f * a;
jamie@140 861 FXTRACT_SQ += f * f;
jamie@48 862 }
jamie@48 863
jamie@146 864 *result = (1.0 / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 865
jamie@56 866 return XTRACT_SUCCESS;
jamie@25 867
jamie@1 868 }
jamie@1 869
jamie@146 870 int xtract_lowest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 871 {
jamie@25 872
jamie@45 873 int n = N;
jamie@45 874
jamie@192 875 *result = DBL_MAX;
jamie@45 876
jamie@140 877 while(n--)
jamie@140 878 {
jamie@192 879 if(data[n] > *(double *)argv)
jamie@140 880 *result = XTRACT_MIN(*result, data[n]);
jamie@45 881 }
jamie@45 882
jamie@192 883 if (*result == DBL_MAX)
jamie@192 884 return XTRACT_NO_RESULT;
jamie@192 885
jamie@56 886 return XTRACT_SUCCESS;
jamie@45 887 }
jamie@45 888
jamie@146 889 int xtract_highest_value(const double *data, const int N, const void *argv, double *result)
jamie@140 890 {
jamie@45 891
jamie@1 892 int n = N;
jamie@1 893
jamie@46 894 *result = data[--n];
jamie@44 895
jamie@140 896 while(n--)
jamie@140 897 *result = XTRACT_MAX(*result, data[n]);
jamie@44 898
jamie@56 899 return XTRACT_SUCCESS;
jamie@1 900 }
jamie@1 901
jamie@45 902
jamie@146 903 int xtract_sum(const double *data, const int N, const void *argv, double *result)
jamie@140 904 {
jamie@45 905
jamie@45 906 int n = N;
jamie@45 907
jamie@146 908 *result = 0.0;
jamie@113 909
jamie@45 910 while(n--)
jamie@140 911 *result += *data++;
jamie@45 912
jamie@56 913 return XTRACT_SUCCESS;
jamie@45 914
jamie@45 915 }
jamie@45 916
jamie@146 917 int xtract_nonzero_count(const double *data, const int N, const void *argv, double *result)
jamie@140 918 {
jamie@59 919
jamie@59 920 int n = N;
jamie@140 921
jamie@146 922 *result = 0.0;
jamie@59 923
jamie@59 924 while(n--)
jamie@140 925 *result += (*data++ ? 1 : 0);
jamie@59 926
jamie@59 927 return XTRACT_SUCCESS;
jamie@59 928
jamie@59 929 }
jamie@59 930
sean@198 931 int xtract_hps(const double *data, const int N, const void *argv, double *result)
jamie@140 932 {
sean@198 933 int n, M, i, peak_index, position1_lwr;
sean@198 934 double tempProduct, peak, largest1_lwr, ratio1;
jamie@1 935
sean@198 936 n = N / 2;
jamie@1 937
sean@198 938 M = ceil(n / 3.0);
jamie@25 939
sean@198 940 if (M <= 1)
jamie@140 941 {
sean@198 942 /* Input data is too short. */
sean@198 943 *result = 0;
sean@198 944 return XTRACT_NO_RESULT;
jamie@1 945 }
jamie@25 946
sean@198 947 tempProduct = peak = 0;
sean@198 948 for (i = 0; i < M; ++i)
sean@198 949 {
sean@198 950 tempProduct = data [i] * data [i * 2] * data [i * 3];
jamie@25 951
sean@198 952 if (tempProduct > peak)
jamie@140 953 {
sean@198 954 peak = tempProduct;
sean@198 955 peak_index = i;
jamie@140 956 }
jamie@1 957 }
jamie@1 958
jamie@1 959 largest1_lwr = position1_lwr = 0;
jamie@1 960
sean@198 961 for(i = 0; i < N; ++i)
jamie@140 962 {
sean@198 963 if(data[i] > largest1_lwr && i != peak_index)
jamie@140 964 {
sean@198 965 largest1_lwr = data[i];
sean@198 966 position1_lwr = i;
jamie@140 967 }
jamie@1 968 }
jamie@1 969
jamie@1 970 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 971
jamie@140 972 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@140 973 peak_index * 0.6 && ratio1 > 0.1)
jamie@140 974 peak_index = position1_lwr;
jamie@1 975
sean@198 976 *result = data [n + peak_index];
sean@196 977
sean@196 978 return XTRACT_SUCCESS;
jamie@1 979 }
jamie@5 980
jamie@146 981 int xtract_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 982 {
jamie@5 983
jamie@78 984 int M, tau, n;
jamie@146 985 double sr;
jamie@43 986 size_t bytes;
jamie@146 987 double f0, err_tau_1, err_tau_x, array_max,
jamie@140 988 threshold_peak, threshold_centre,
jamie@140 989 *input;
jamie@22 990
jamie@146 991 sr = *(double *)argv;
jamie@78 992 if(sr == 0)
jamie@146 993 sr = 44100.0;
jamie@43 994
jamie@146 995 input = (double *)malloc(bytes = N * sizeof(double));
jamie@43 996 input = memcpy(input, data, bytes);
jamie@146 997 /* threshold_peak = *((double *)argv+1);
jamie@146 998 threshold_centre = *((double *)argv+2);
jamie@146 999 printf("peak: %.2\tcentre: %.2\n", threshold_peak, threshold_centre);*/
jamie@25 1000 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 1001
jamie@25 1002 /* FIX: tweak and make into macros */
jamie@25 1003 threshold_peak = .8;
jamie@25 1004 threshold_centre = .3;
jamie@25 1005 M = N >> 1;
jamie@25 1006 err_tau_1 = 0;
jamie@25 1007 array_max = 0;
jamie@25 1008
jamie@25 1009 /* Find the array max */
jamie@140 1010 for(n = 0; n < N; n++)
jamie@140 1011 {
jamie@140 1012 if (input[n] > array_max)
jamie@140 1013 array_max = input[n];
jamie@12 1014 }
jamie@25 1015
jamie@25 1016 threshold_peak *= array_max;
jamie@25 1017
jamie@25 1018 /* peak clip */
jamie@140 1019 for(n = 0; n < N; n++)
jamie@140 1020 {
jamie@140 1021 if(input[n] > threshold_peak)
jamie@140 1022 input[n] = threshold_peak;
jamie@140 1023 else if(input[n] < -threshold_peak)
jamie@140 1024 input[n] = -threshold_peak;
jamie@25 1025 }
jamie@25 1026
jamie@25 1027 threshold_centre *= array_max;
jamie@25 1028
jamie@25 1029 /* Centre clip */
jamie@140 1030 for(n = 0; n < N; n++)
jamie@140 1031 {
jamie@140 1032 if (input[n] < threshold_centre)
jamie@140 1033 input[n] = 0;
jamie@140 1034 else
jamie@140 1035 input[n] -= threshold_centre;
jamie@25 1036 }
jamie@25 1037
jamie@25 1038 /* Estimate fundamental freq */
jamie@25 1039 for (n = 1; n < M; n++)
jamie@146 1040 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@140 1041 /* 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 1042 for (tau = 2; tau < M; tau++)
jamie@140 1043 {
jamie@140 1044 err_tau_x = 0;
jamie@140 1045 for (n = 1; n < M; n++)
jamie@140 1046 {
jamie@146 1047 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@140 1048 }
jamie@140 1049 if (err_tau_x < err_tau_1)
jamie@140 1050 {
jamie@140 1051 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@140 1052 *result = f0;
jamie@140 1053 free(input);
jamie@140 1054 return XTRACT_SUCCESS;
jamie@140 1055 }
jamie@25 1056 }
jamie@43 1057 *result = -0;
jamie@43 1058 free(input);
jamie@56 1059 return XTRACT_NO_RESULT;
jamie@5 1060 }
jamie@43 1061
jamie@146 1062 int xtract_failsafe_f0(const double *data, const int N, const void *argv, double *result)
jamie@140 1063 {
jamie@44 1064
jamie@146 1065 double *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 1066
jamie@43 1067 return_code = xtract_f0(data, N, argv, result);
jamie@44 1068
jamie@140 1069 if(return_code == XTRACT_NO_RESULT)
jamie@140 1070 {
jamie@146 1071 sr = *(double *)argv;
jamie@140 1072 if(sr == 0)
jamie@146 1073 sr = 44100.0;
jamie@146 1074 spectrum = (double *)malloc(N * sizeof(double));
jamie@146 1075 peaks = (double *)malloc(N * sizeof(double));
jamie@140 1076 argf[0] = sr;
jamie@140 1077 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@140 1078 xtract_spectrum(data, N, argf, spectrum);
jamie@146 1079 argf[1] = 10.0;
jamie@140 1080 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@146 1081 argf[0] = 0.0;
jamie@140 1082 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 1083
jamie@140 1084 free(spectrum);
jamie@140 1085 free(peaks);
jamie@43 1086 }
jamie@43 1087
jamie@56 1088 return XTRACT_SUCCESS;
jamie@43 1089
jamie@43 1090 }
jamie@44 1091
jamie@161 1092 int xtract_wavelet_f0(const double *data, const int N, const void *argv, double *result)
jamie@161 1093 {
jamie@169 1094 /* double sr = *(double *)argv; */
jamie@161 1095
jamie@161 1096 *result = dywapitch_computepitch(&wavelet_f0_state, data, 0, N);
jamie@161 1097
jamie@161 1098 if (*result == 0.0)
jamie@161 1099 {
jamie@161 1100 return XTRACT_NO_RESULT;
jamie@161 1101 }
jamie@161 1102
jamie@161 1103 return XTRACT_SUCCESS;
jamie@161 1104 }
jamie@161 1105
jamie@161 1106