annotate src/scalar.c @ 285:89fe52066db1 tip master

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