annotate src/scalar.c @ 152:07aa4d2af390

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