annotate src/scalar.c @ 227:cabf2f465d1b

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