annotate src/scalar.c @ 246:bde5fa8692ff

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