annotate src/scalar.c @ 55:4ea1a8838b14

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