annotate src/scalar.c @ 140:67f6b6e63d45

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