annotate src/scalar.c @ 122:571c53e87dbd

- fixed typos in *result initialisation potentially fixing horrible bug
author Jamie Bullock <jamie@postlude.co.uk>
date Wed, 30 Mar 2011 10:05:07 +0000
parents 2b2d0609e44f
children efb1c1ae2ba8
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@53 189 A += amps[m];
jamie@59 190 *result += powf((freqs[m] - *(float *)argv) * amps[m], 2);
jamie@53 191 }
jamie@53 192
jamie@59 193 *result = *result / (A /*- 1*/);
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@52 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@53 219 A += amps[m];
jamie@113 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@52 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 float temp, A = 0.f;
jamie@53 232 const float *freqs, *amps;
jamie@52 233
jamie@53 234 m = N >> 1;
jamie@53 235
jamie@53 236 amps = data;
jamie@53 237 freqs = data + m;
jamie@52 238
jamie@122 239 *result = 0.f;
jamie@113 240
jamie@52 241 while(m--){
jamie@53 242 A += amps[m];
jamie@53 243 temp = ((amps[m] * freqs[m]) -
jamie@52 244 ((float *)argv)[0]) / ((float *)argv)[1];
jamie@113 245 *result += powf(temp, 3);
jamie@52 246 }
jamie@52 247
jamie@53 248 *result /= A;
jamie@52 249
jamie@56 250 return XTRACT_SUCCESS;
jamie@52 251 }
jamie@52 252
jamie@52 253 int xtract_spectral_kurtosis(const float *data, const int N, const void *argv, float *result){
jamie@52 254
jamie@53 255 int m;
jamie@53 256 float temp, A = 0.f;
jamie@53 257 const float *freqs, *amps;
jamie@52 258
jamie@53 259 m = N >> 1;
jamie@53 260
jamie@53 261 amps = data;
jamie@53 262 freqs = data + m;
jamie@52 263
jamie@122 264 *result = 0.f;
jamie@113 265
jamie@52 266 while(m--){
jamie@53 267 A += amps[m];
jamie@53 268 temp = ((amps[m] * freqs[m]) -
jamie@52 269 ((float *)argv)[0]) / ((float *)argv)[1];
jamie@113 270 *result += powf(temp, 4);
jamie@52 271 }
jamie@52 272
jamie@53 273 *result /= A;
jamie@52 274 *result -= 3.0f;
jamie@52 275
jamie@56 276 return XTRACT_SUCCESS;
jamie@52 277 }
jamie@52 278
jamie@43 279 int xtract_irregularity_k(const float *data, const int N, const void *argv, float *result){
jamie@25 280
jamie@1 281 int n,
jamie@37 282 M = N - 1;
danstowell@84 283
jamie@113 284 *result = 0.f;
danstowell@84 285
jamie@1 286 for(n = 1; n < M; n++)
jamie@113 287 *result += fabsf(data[n] - (data[n-1] + data[n] + data[n+1]) / 3.f);
jamie@1 288
jamie@56 289 return XTRACT_SUCCESS;
jamie@1 290 }
jamie@1 291
jamie@43 292 int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result){
jamie@25 293
jamie@1 294 int n = N;
jamie@1 295
jamie@59 296 double num = 0.f, den = 0.f;
jamie@1 297
jamie@1 298 while(n--){
jamie@113 299 num += powf(data[n] - data[n+1], 2);
jamie@113 300 den += powf(data[n], 2);
jamie@1 301 }
jamie@25 302
jamie@59 303 *result = (float)(num / den);
jamie@1 304
jamie@56 305 return XTRACT_SUCCESS;
jamie@1 306 }
jamie@1 307
jamie@43 308 int xtract_tristimulus_1(const float *data, const int N, const void *argv, float *result){
jamie@1 309
jamie@1 310 int n = N;
jamie@1 311
jamie@42 312 float den, p1, temp;
jamie@1 313
jamie@42 314 den = p1 = temp = 0.f;
jamie@1 315
jamie@42 316 for(n = 0; n < N; n++){
jamie@42 317 if((temp = data[n])){
jamie@42 318 den += temp;
jamie@42 319 if(!p1)
jamie@42 320 p1 = temp;
jamie@42 321 }
jamie@42 322 }
jamie@42 323
jamie@113 324 if(den == 0.f || p1 == 0.f){
jamie@113 325 *result = 0.f;
jamie@113 326 return XTRACT_NO_RESULT;
jamie@113 327 }
jamie@113 328 else{
jamie@113 329 *result = p1 / den;
jamie@113 330 return XTRACT_SUCCESS;
jamie@113 331 }
jamie@1 332 }
jamie@1 333
jamie@43 334 int xtract_tristimulus_2(const float *data, const int N, const void *argv, float *result){
jamie@25 335
jamie@1 336 int n = N;
jamie@1 337
jamie@113 338 float den, p2, p3, p4, ps, temp;
jamie@1 339
jamie@113 340 den = p2 = p3 = p4 = ps = temp = 0.f;
jamie@1 341
jamie@42 342 for(n = 0; n < N; n++){
jamie@42 343 if((temp = data[n])){
jamie@42 344 den += temp;
jamie@42 345 if(!p2)
jamie@42 346 p2 = temp;
jamie@42 347 else if(!p3)
jamie@42 348 p3 = temp;
jamie@42 349 else if(!p4)
jamie@42 350 p4 = temp;
jamie@42 351 }
jamie@42 352 }
jamie@42 353
jamie@113 354 ps = p2 + p3 + p4;
jamie@25 355
jamie@113 356 if(den == 0.f || ps == 0.f){
jamie@113 357 *result = 0.f;
jamie@113 358 return XTRACT_NO_RESULT;
jamie@113 359 }
jamie@113 360 else{
jamie@113 361 *result = ps / den;
jamie@113 362 return XTRACT_SUCCESS;
jamie@113 363 }
jamie@113 364
jamie@1 365 }
jamie@1 366
jamie@43 367 int xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result){
jamie@25 368
jamie@42 369 int n = N, count = 0;
jamie@1 370
jamie@42 371 float den, num, temp;
jamie@1 372
jamie@42 373 den = num = temp = 0.f;
jamie@1 374
jamie@42 375 for(n = 0; n < N; n++){
jamie@42 376 if((temp = data[n])){
jamie@42 377 den += temp;
jamie@42 378 if(count >= 5)
jamie@42 379 num += temp;
jamie@42 380 count++;
jamie@42 381 }
jamie@42 382 }
jamie@25 383
jamie@113 384 if(den == 0.f || num == 0.f){
jamie@113 385 *result = 0.f;
jamie@113 386 return XTRACT_NO_RESULT;
jamie@113 387 }
jamie@113 388 else{
jamie@113 389 *result = num / den;
jamie@113 390 return XTRACT_SUCCESS;
jamie@113 391 }
jamie@1 392 }
jamie@1 393
jamie@43 394 int xtract_smoothness(const float *data, const int N, const void *argv, float *result){
jamie@25 395
jamie@59 396 int n, M;
jamie@1 397
jamie@43 398 float *input;
jamie@43 399
jamie@43 400 input = (float *)malloc(N * sizeof(float));
jamie@59 401 memcpy(input, data, N * sizeof(float));
jamie@43 402
jamie@113 403 if (input[0] <= 0)
jamie@113 404 input[0] = XTRACT_LOG_LIMIT;
jamie@113 405 if (input[1] <= 0)
jamie@113 406 input[1] = XTRACT_LOG_LIMIT;
jamie@25 407
jamie@59 408 M = N - 1;
jamie@59 409
jamie@59 410 for(n = 1; n < M; n++){
jamie@113 411 if(input[n+1] <= 0)
jamie@113 412 input[n+1] = XTRACT_LOG_LIMIT;
jamie@113 413 *result += fabsf(20.f * logf(input[n]) - (20.f * logf(input[n-1]) +
jamie@113 414 20.f * logf(input[n]) + 20.f * logf(input[n+1])) / 3.f);
jamie@25 415 }
jamie@43 416
jamie@43 417 free(input);
jamie@44 418
jamie@56 419 return XTRACT_SUCCESS;
jamie@1 420 }
jamie@1 421
jamie@43 422 int xtract_spread(const float *data, const int N, const void *argv, float *result){
jamie@1 423
jamie@1 424 int n = N;
jamie@1 425
jamie@83 426 float num = 0.f, den = 0.f, temp = 0.f;
jamie@83 427
jamie@83 428 if(argv == NULL)
jamie@83 429 return XTRACT_BAD_ARGV;
jamie@1 430
jamie@1 431 while(n--){
jamie@48 432 temp = n - *(float *)argv;
jamie@56 433 num += XTRACT_SQ(temp) * data[n];
jamie@25 434 den += data[n];
jamie@1 435 }
jamie@1 436
jamie@117 437 /* FIX: spectral spread is mathematically equivalent to spectral variance --
jamie@117 438 * here we are computing the spectral standard deviation */
jamie@113 439 *result = sqrtf(num / den);
jamie@25 440
jamie@56 441 return XTRACT_SUCCESS;
jamie@1 442 }
jamie@1 443
jamie@43 444 int xtract_zcr(const float *data, const int N, const void *argv, float *result){
jamie@1 445
jamie@1 446 int n = N;
jamie@25 447
jamie@1 448 for(n = 1; n < N; n++)
jamie@25 449 if(data[n] * data[n-1] < 0) (*result)++;
jamie@25 450
jamie@113 451 *result /= (float)N;
jamie@25 452
jamie@56 453 return XTRACT_SUCCESS;
jamie@1 454 }
jamie@1 455
jamie@43 456 int xtract_rolloff(const float *data, const int N, const void *argv, float *result){
jamie@1 457
jamie@1 458 int n = N;
jamie@55 459 float pivot, temp, percentile;
jamie@42 460
jamie@42 461 pivot = temp = 0.f;
jamie@55 462 percentile = ((float *)argv)[1];
jamie@25 463
jamie@1 464 while(n--) pivot += data[n];
jamie@25 465
jamie@55 466 pivot *= percentile / 100.f;
jamie@25 467
jamie@42 468 for(n = 0; temp < pivot; n++)
jamie@42 469 temp += data[n];
jamie@1 470
jamie@55 471 *result = n * ((float *)argv)[0];
jamie@55 472 /* *result = (n / (float)N) * (((float *)argv)[1] * .5); */
jamie@25 473
jamie@56 474 return XTRACT_SUCCESS;
jamie@1 475 }
jamie@1 476
jamie@43 477 int xtract_loudness(const float *data, const int N, const void *argv, float *result){
jamie@25 478
jamie@47 479 int n = N, rv;
jamie@25 480
jamie@113 481 *result = 0.f;
jamie@113 482
jamie@93 483 if(n > XTRACT_BARK_BANDS){
jamie@93 484 n = XTRACT_BARK_BANDS;
jamie@56 485 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@93 486 }
jamie@47 487 else
jamie@56 488 rv = XTRACT_SUCCESS;
jamie@1 489
jamie@1 490 while(n--)
jamie@59 491 *result += powf(data[n], 0.23);
jamie@38 492
jamie@47 493 return rv;
jamie@1 494 }
jamie@1 495
jamie@43 496 int xtract_flatness(const float *data, const int N, const void *argv, float *result){
jamie@1 497
jamie@113 498 int n, count, denormal_found;
jamie@1 499
jamie@44 500 double num, den, temp;
jamie@25 501
jamie@113 502 num = 1.f;
jamie@113 503 den = temp = 0.f;
jamie@43 504
jamie@113 505 denormal_found = 0;
jamie@113 506 count = 0;
jamie@113 507
jamie@113 508 for(n = 0; n < N; n++){
jamie@113 509 if((temp = data[n]) != 0.f) {
jamie@113 510 if (xtract_is_denormal(num)){
jamie@113 511 denormal_found = 1;
jamie@113 512 break;
jamie@113 513 }
jamie@113 514 num *= temp;
jamie@113 515 den += temp;
jamie@113 516 count++;
jamie@113 517 }
jamie@1 518 }
jamie@44 519
jamie@113 520 if(!count){
jamie@113 521 *result = 0.f;
jamie@113 522 return XTRACT_NO_RESULT;
jamie@113 523 }
jamie@25 524
jamie@113 525 num = powf(num, 1.f / (float)N);
jamie@113 526 den /= (float)N;
jamie@44 527
jamie@44 528
jamie@113 529 *result = (float) (num / den);
jamie@113 530
jamie@113 531 if(denormal_found)
jamie@113 532 return XTRACT_DENORMAL_FOUND;
jamie@113 533 else
jamie@113 534 return XTRACT_SUCCESS;
jamie@113 535
jamie@113 536 }
jamie@113 537
jamie@113 538 int xtract_flatness_db(const float *data, const int N, const void *argv, float *result){
jamie@113 539
jamie@115 540 float flatness;
jamie@113 541
jamie@115 542 flatness = *(float *)argv;
jamie@113 543
jamie@115 544 if (flatness <= 0)
jamie@115 545 flatness = XTRACT_LOG_LIMIT;
jamie@113 546
jamie@115 547 *result = 10 * log10f(flatness);
jamie@25 548
jamie@56 549 return XTRACT_SUCCESS;
jamie@44 550
jamie@1 551 }
jamie@1 552
jamie@43 553 int xtract_tonality(const float *data, const int N, const void *argv, float *result){
jamie@25 554
jamie@113 555 float sfmdb;
jamie@25 556
jamie@113 557 sfmdb = *(float *)argv;
jamie@1 558
jamie@113 559 *result = XTRACT_MIN(sfmdb / -60.f, 1);
jamie@25 560
jamie@56 561 return XTRACT_SUCCESS;
jamie@1 562 }
jamie@1 563
jamie@43 564 int xtract_crest(const float *data, const int N, const void *argv, float *result){
jamie@25 565
jamie@45 566 float max, mean;
jamie@45 567
jamie@45 568 max = mean = 0.f;
jamie@45 569
jamie@45 570 max = *(float *)argv;
jamie@45 571 mean = *((float *)argv+1);
jamie@45 572
jamie@45 573 *result = max / mean;
jamie@45 574
jamie@56 575 return XTRACT_SUCCESS;
jamie@25 576
jamie@1 577 }
jamie@1 578
jamie@43 579 int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
jamie@25 580
jamie@45 581 float h, i, p; /*harmonics, inharmonics, partials */
jamie@45 582
jamie@45 583 i = p = h = 0.f;
jamie@45 584
jamie@45 585 h = *(float *)argv;
jamie@45 586 p = *((float *)argv+1);
jamie@45 587
jamie@45 588 i = p - h;
jamie@45 589
jamie@45 590 *result = i / p;
jamie@45 591
jamie@56 592 return XTRACT_SUCCESS;
jamie@25 593
jamie@1 594 }
jamie@2 595
jamie@43 596 int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
jamie@1 597
jamie@1 598 int n = N;
jamie@1 599
jamie@113 600 *result = 0.f;
jamie@113 601
jamie@56 602 while(n--) *result += XTRACT_SQ(data[n]);
jamie@1 603
jamie@113 604 *result = sqrtf(*result / (float)N);
jamie@25 605
jamie@56 606 return XTRACT_SUCCESS;
jamie@1 607 }
jamie@1 608
jamie@52 609 int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result){
jamie@1 610
jamie@41 611 int n = N >> 1;
jamie@43 612 float num = 0.f, den = 0.f, fund;
jamie@43 613 const float *freqs, *amps;
jamie@1 614
jamie@41 615 fund = *(float *)argv;
jamie@52 616 amps = data;
jamie@52 617 freqs = data + n;
jamie@25 618
jamie@1 619 while(n--){
jamie@59 620 if(amps[n]){
jamie@113 621 num += fabsf(freqs[n] - n * fund) * XTRACT_SQ(amps[n]);
jamie@59 622 den += XTRACT_SQ(amps[n]);
jamie@59 623 }
jamie@1 624 }
jamie@1 625
jamie@41 626 *result = (2 * num) / (fund * den);
jamie@25 627
jamie@56 628 return XTRACT_SUCCESS;
jamie@1 629 }
jamie@1 630
jamie@1 631
jamie@43 632 int xtract_power(const float *data, const int N, const void *argv, float *result){
jamie@1 633
jamie@56 634 return XTRACT_FEATURE_NOT_IMPLEMENTED;
jamie@25 635
jamie@1 636 }
jamie@1 637
jamie@43 638 int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
jamie@1 639
jamie@43 640 int M = (N >> 1), n;
jamie@1 641
jamie@113 642 float odd = 0.f, even = 0.f, temp;
jamie@44 643
jamie@43 644 for(n = 0; n < M; n++){
jamie@43 645 if((temp = data[n])){
jamie@59 646 if(XTRACT_IS_ODD(n)){
jamie@113 647 odd += temp;
jamie@43 648 }
jamie@43 649 else{
jamie@113 650 even += temp;
jamie@43 651 }
jamie@43 652 }
jamie@1 653 }
jamie@1 654
jamie@113 655 if(odd == 0.f || even == 0.f){
jamie@113 656 *result = 0.f;
jamie@113 657 return XTRACT_NO_RESULT;
jamie@113 658 }
jamie@113 659 else {
jamie@113 660 *result = odd / even;
jamie@113 661 return XTRACT_SUCCESS;
jamie@113 662 }
jamie@1 663 }
jamie@1 664
jamie@43 665 int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
jamie@1 666
jamie@48 667 int n = N, rv;
jamie@113 668 float sl, g; /* sl = specific loudness */
jamie@113 669 double temp;
jamie@48 670
jamie@113 671 sl = g = 0.f;
jamie@113 672 temp = 0.f;
jamie@48 673
jamie@56 674 if(n > XTRACT_BARK_BANDS)
jamie@56 675 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 676 else
jamie@56 677 rv = XTRACT_SUCCESS;
jamie@48 678
jamie@48 679
jamie@48 680 while(n--){
jamie@59 681 sl = powf(data[n], 0.23);
jamie@59 682 g = (n < 15 ? 1.f : 0.066 * expf(0.171 * n));
jamie@49 683 temp += n * g * sl;
jamie@48 684 }
jamie@48 685
jamie@113 686 temp = 0.11 * temp / (float)N;
jamie@113 687 *result = (float)temp;
jamie@48 688
jamie@48 689 return rv;
jamie@25 690
jamie@1 691 }
jamie@1 692
jamie@52 693 int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result){
jamie@1 694
jamie@48 695 const float *freqs, *amps;
jamie@48 696 float f, a,
jamie@56 697 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@48 698 int n, M;
jamie@48 699
jamie@56 700 F = A = FA = FXTRACT_SQ = 0.f;
jamie@48 701 n = M = N >> 1;
jamie@48 702
jamie@52 703 amps = data;
jamie@52 704 freqs = data + n;
jamie@48 705
jamie@48 706 while(n--){
jamie@48 707 f = freqs[n];
jamie@48 708 a = amps[n];
jamie@48 709 F += f;
jamie@48 710 A += a;
jamie@48 711 FA += f * a;
jamie@56 712 FXTRACT_SQ += f * f;
jamie@48 713 }
jamie@48 714
jamie@56 715 *result = (1.f / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 716
jamie@56 717 return XTRACT_SUCCESS;
jamie@25 718
jamie@1 719 }
jamie@1 720
jamie@45 721 int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){
jamie@25 722
jamie@45 723 int n = N;
jamie@45 724 float temp;
jamie@45 725
jamie@46 726 *result = data[--n];
jamie@45 727
jamie@45 728 while(n--){
jamie@45 729 if((temp = data[n]) > *(float *)argv)
jamie@56 730 *result = XTRACT_MIN(*result, data[n]);
jamie@45 731 }
jamie@45 732
jamie@56 733 return XTRACT_SUCCESS;
jamie@45 734 }
jamie@45 735
jamie@45 736 int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
jamie@45 737
jamie@1 738 int n = N;
jamie@1 739
jamie@46 740 *result = data[--n];
jamie@44 741
jamie@45 742 while(n--)
jamie@56 743 *result = XTRACT_MAX(*result, data[n]);
jamie@44 744
jamie@56 745 return XTRACT_SUCCESS;
jamie@1 746 }
jamie@1 747
jamie@45 748
jamie@45 749 int xtract_sum(const float *data, const int N, const void *argv, float *result){
jamie@45 750
jamie@45 751 int n = N;
jamie@45 752
jamie@113 753 *result = 0.f;
jamie@113 754
jamie@45 755 while(n--)
jamie@45 756 *result += *data++;
jamie@45 757
jamie@56 758 return XTRACT_SUCCESS;
jamie@45 759
jamie@45 760 }
jamie@45 761
jamie@59 762 int xtract_nonzero_count(const float *data, const int N, const void *argv, float *result){
jamie@59 763
jamie@59 764 int n = N;
jamie@113 765
jamie@122 766 *result = 0.f;
jamie@59 767
jamie@59 768 while(n--)
jamie@59 769 *result += (*data++ ? 1 : 0);
jamie@59 770
jamie@59 771 return XTRACT_SUCCESS;
jamie@59 772
jamie@59 773 }
jamie@59 774
jamie@43 775 int xtract_hps(const float *data, const int N, const void *argv, float *result){
jamie@1 776
jamie@1 777 int n = N, M, m, l, peak_index, position1_lwr;
jamie@1 778 float *coeffs2, *coeffs3, *product, L,
jamie@25 779 largest1_lwr, peak, ratio1, sr;
jamie@1 780
jamie@25 781 sr = *(float*)argv;
jamie@78 782 if(sr == 0)
jamie@78 783 sr = 44100.f;
jamie@25 784
jamie@1 785 coeffs2 = (float *)malloc(N * sizeof(float));
jamie@1 786 coeffs3 = (float *)malloc(N * sizeof(float));
jamie@1 787 product = (float *)malloc(N * sizeof(float));
jamie@25 788
jamie@1 789 while(n--) coeffs2[n] = coeffs3[n] = 1;
jamie@1 790
jamie@1 791 M = N >> 1;
jamie@113 792 L = N / 3.f;
jamie@1 793
jamie@1 794 while(M--){
jamie@25 795 m = M << 1;
jamie@25 796 coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
jamie@1 797
jamie@25 798 if(M < L){
jamie@25 799 l = M * 3;
jamie@113 800 coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3.f;
jamie@25 801 }
jamie@1 802 }
jamie@25 803
jamie@1 804 peak_index = peak = 0;
jamie@25 805
jamie@1 806 for(n = 1; n < N; n++){
jamie@25 807 product[n] = data[n] * coeffs2[n] * coeffs3[n];
jamie@25 808 if(product[n] > peak){
jamie@25 809 peak_index = n;
jamie@25 810 peak = product[n];
jamie@25 811 }
jamie@1 812 }
jamie@1 813
jamie@1 814 largest1_lwr = position1_lwr = 0;
jamie@1 815
jamie@1 816 for(n = 0; n < N; n++){
jamie@25 817 if(data[n] > largest1_lwr && n != peak_index){
jamie@25 818 largest1_lwr = data[n];
jamie@25 819 position1_lwr = n;
jamie@25 820 }
jamie@1 821 }
jamie@1 822
jamie@1 823 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 824
jamie@1 825 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@25 826 peak_index * 0.6 && ratio1 > 0.1)
jamie@25 827 peak_index = position1_lwr;
jamie@1 828
jamie@22 829 *result = sr / (float)peak_index;
jamie@25 830
jamie@1 831 free(coeffs2);
jamie@1 832 free(coeffs3);
jamie@1 833 free(product);
jamie@25 834
jamie@56 835 return XTRACT_SUCCESS;
jamie@1 836 }
jamie@5 837
jamie@5 838
jamie@43 839 int xtract_f0(const float *data, const int N, const void *argv, float *result){
jamie@5 840
jamie@78 841 int M, tau, n;
jamie@78 842 float sr;
jamie@43 843 size_t bytes;
jamie@43 844 float f0, err_tau_1, err_tau_x, array_max,
jamie@43 845 threshold_peak, threshold_centre,
jamie@43 846 *input;
jamie@22 847
jamie@25 848 sr = *(float *)argv;
jamie@78 849 if(sr == 0)
jamie@78 850 sr = 44100.f;
jamie@43 851
jamie@43 852 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 853 input = memcpy(input, data, bytes);
jamie@25 854 /* threshold_peak = *((float *)argv+1);
jamie@25 855 threshold_centre = *((float *)argv+2);
jamie@25 856 printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
jamie@25 857 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 858
jamie@25 859 /* FIX: tweak and make into macros */
jamie@25 860 threshold_peak = .8;
jamie@25 861 threshold_centre = .3;
jamie@25 862 M = N >> 1;
jamie@25 863 err_tau_1 = 0;
jamie@25 864 array_max = 0;
jamie@25 865
jamie@25 866 /* Find the array max */
jamie@25 867 for(n = 0; n < N; n++){
jamie@43 868 if (input[n] > array_max)
jamie@43 869 array_max = input[n];
jamie@12 870 }
jamie@25 871
jamie@25 872 threshold_peak *= array_max;
jamie@25 873
jamie@25 874 /* peak clip */
jamie@25 875 for(n = 0; n < N; n++){
jamie@43 876 if(input[n] > threshold_peak)
jamie@43 877 input[n] = threshold_peak;
jamie@43 878 else if(input[n] < -threshold_peak)
jamie@43 879 input[n] = -threshold_peak;
jamie@25 880 }
jamie@25 881
jamie@25 882 threshold_centre *= array_max;
jamie@25 883
jamie@25 884 /* Centre clip */
jamie@25 885 for(n = 0; n < N; n++){
jamie@43 886 if (input[n] < threshold_centre)
jamie@43 887 input[n] = 0;
jamie@25 888 else
jamie@43 889 input[n] -= threshold_centre;
jamie@25 890 }
jamie@25 891
jamie@25 892 /* Estimate fundamental freq */
jamie@25 893 for (n = 1; n < M; n++)
jamie@113 894 err_tau_1 = err_tau_1 + fabsf(input[n] - input[n+1]);
jamie@25 895 /* 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 896 for (tau = 2; tau < M; tau++){
jamie@25 897 err_tau_x = 0;
jamie@25 898 for (n = 1; n < M; n++){
jamie@113 899 err_tau_x = err_tau_x + fabsf(input[n] - input[n+tau]);
jamie@25 900 }
jamie@25 901 if (err_tau_x < err_tau_1) {
jamie@25 902 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@25 903 *result = f0;
jamie@43 904 free(input);
jamie@56 905 return XTRACT_SUCCESS;
jamie@25 906 }
jamie@25 907 }
jamie@43 908 *result = -0;
jamie@43 909 free(input);
jamie@56 910 return XTRACT_NO_RESULT;
jamie@5 911 }
jamie@43 912
jamie@43 913 int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
jamie@44 914
jamie@59 915 float *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 916
jamie@43 917 return_code = xtract_f0(data, N, argv, result);
jamie@44 918
jamie@56 919 if(return_code == XTRACT_NO_RESULT){
jamie@44 920
jamie@59 921 sr = *(float *)argv;
jamie@78 922 if(sr == 0)
jamie@78 923 sr = 44100.f;
jamie@59 924 spectrum = (float *)malloc(N * sizeof(float));
jamie@43 925 peaks = (float *)malloc(N * sizeof(float));
jamie@59 926 argf[0] = sr;
jamie@59 927 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@59 928 xtract_spectrum(data, N, argf, spectrum);
jamie@59 929 argf[1] = 10.f;
jamie@59 930 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@43 931 argf[0] = 0.f;
jamie@59 932 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 933
jamie@59 934 free(spectrum);
jamie@43 935 free(peaks);
jamie@43 936 }
jamie@43 937
jamie@56 938 return XTRACT_SUCCESS;
jamie@43 939
jamie@43 940 }
jamie@44 941