annotate src/scalar.c @ 93:61fe1af213cd

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