annotate src/scalar.c @ 161:246c203cc733

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