annotate src/scalar.c @ 129:a34ea87daa58

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