annotate src/scalar.c @ 53:04f536b139a8

Made some changes to spectral_mean etc.
author Jamie Bullock <jamie@postlude.co.uk>
date Wed, 10 Jan 2007 14:36:43 +0000
parents 45c585bb7996
children 9762d7e3d129
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@42 377 float pivot, temp;
jamie@42 378
jamie@42 379 pivot = temp = 0.f;
jamie@25 380
jamie@1 381 while(n--) pivot += data[n];
jamie@25 382
jamie@42 383 pivot *= ((float *)argv)[0];
jamie@25 384
jamie@42 385 for(n = 0; temp < pivot; n++)
jamie@42 386 temp += data[n];
jamie@1 387
jamie@42 388 *result = (n / (float)N) * (((float *)argv)[1] * .5);
jamie@25 389
jamie@38 390 return SUCCESS;
jamie@1 391 }
jamie@1 392
jamie@43 393 int xtract_loudness(const float *data, const int N, const void *argv, float *result){
jamie@25 394
jamie@47 395 int n = N, rv;
jamie@25 396
jamie@47 397 if(n > BARK_BANDS)
jamie@47 398 rv = BAD_VECTOR_SIZE;
jamie@47 399 else
jamie@47 400 rv = SUCCESS;
jamie@1 401
jamie@1 402 while(n--)
jamie@25 403 *result += pow(data[n], 0.23);
jamie@38 404
jamie@47 405 return rv;
jamie@1 406 }
jamie@1 407
jamie@43 408 int xtract_flatness(const float *data, const int N, const void *argv, float *result){
jamie@1 409
jamie@42 410 int n;
jamie@1 411
jamie@44 412 double num, den, temp;
jamie@25 413
jamie@44 414 den = data[0];
jamie@44 415 num = (data[0] == 0.f ? 1.f : data[0]);
jamie@43 416
jamie@44 417 for(n = 1; n < N; n++){
jamie@44 418 if((temp = data[n]) != 0.f) {
jamie@44 419 num *= temp;
jamie@44 420 den += temp;
jamie@25 421 }
jamie@1 422 }
jamie@44 423
jamie@44 424 num = pow(num, 1.f / N);
jamie@1 425 den /= N;
jamie@25 426
jamie@45 427 if(num < VERY_SMALL_NUMBER)
jamie@45 428 num = VERY_SMALL_NUMBER;
jamie@44 429
jamie@45 430 if(den < VERY_SMALL_NUMBER)
jamie@45 431 den = VERY_SMALL_NUMBER;
jamie@44 432
jamie@42 433 *result = num / den;
jamie@25 434
jamie@38 435 return SUCCESS;
jamie@44 436
jamie@1 437 }
jamie@1 438
jamie@43 439 int xtract_tonality(const float *data, const int N, const void *argv, float *result){
jamie@25 440
jamie@1 441 float sfmdb, sfm;
jamie@25 442
jamie@1 443 sfm = *(float *)argv;
jamie@1 444
jamie@45 445 sfmdb = (sfm > 0 ? ((10 * log10(sfm)) / -60) : 0);
jamie@25 446
jamie@1 447 *result = MIN(sfmdb, 1);
jamie@25 448
jamie@38 449 return SUCCESS;
jamie@1 450 }
jamie@1 451
jamie@43 452 int xtract_crest(const float *data, const int N, const void *argv, float *result){
jamie@25 453
jamie@45 454 float max, mean;
jamie@45 455
jamie@45 456 max = mean = 0.f;
jamie@45 457
jamie@45 458 max = *(float *)argv;
jamie@45 459 mean = *((float *)argv+1);
jamie@45 460
jamie@45 461 *result = max / mean;
jamie@45 462
jamie@45 463 return SUCCESS;
jamie@25 464
jamie@1 465 }
jamie@1 466
jamie@43 467 int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
jamie@25 468
jamie@45 469 float h, i, p; /*harmonics, inharmonics, partials */
jamie@45 470
jamie@45 471 i = p = h = 0.f;
jamie@45 472
jamie@45 473 h = *(float *)argv;
jamie@45 474 p = *((float *)argv+1);
jamie@45 475
jamie@45 476 i = p - h;
jamie@45 477
jamie@45 478 *result = i / p;
jamie@45 479
jamie@45 480 return SUCCESS;
jamie@25 481
jamie@1 482 }
jamie@2 483
jamie@43 484 int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
jamie@1 485
jamie@1 486 int n = N;
jamie@1 487
jamie@1 488 while(n--) *result += SQ(data[n]);
jamie@1 489
jamie@1 490 *result = sqrt(*result / N);
jamie@25 491
jamie@38 492 return SUCCESS;
jamie@1 493 }
jamie@1 494
jamie@52 495 int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result){
jamie@1 496
jamie@41 497 int n = N >> 1;
jamie@43 498 float num = 0.f, den = 0.f, fund;
jamie@43 499 const float *freqs, *amps;
jamie@1 500
jamie@41 501 fund = *(float *)argv;
jamie@52 502 amps = data;
jamie@52 503 freqs = data + n;
jamie@25 504
jamie@1 505 while(n--){
jamie@41 506 num += abs(freqs[n] - n * fund) * SQ(amps[n]);
jamie@41 507 den += SQ(amps[n]);
jamie@1 508 }
jamie@1 509
jamie@41 510 *result = (2 * num) / (fund * den);
jamie@25 511
jamie@38 512 return SUCCESS;
jamie@1 513 }
jamie@1 514
jamie@1 515
jamie@43 516 int xtract_power(const float *data, const int N, const void *argv, float *result){
jamie@1 517
jamie@38 518 return FEATURE_NOT_IMPLEMENTED;
jamie@25 519
jamie@1 520 }
jamie@1 521
jamie@43 522 int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
jamie@1 523
jamie@43 524 int M = (N >> 1), n;
jamie@1 525
jamie@43 526 float num = 0.f, den = 0.f, temp, f0;
jamie@1 527
jamie@43 528 f0 = *(float *)argv;
jamie@44 529
jamie@43 530 for(n = 0; n < M; n++){
jamie@43 531 if((temp = data[n])){
jamie@43 532 if(((int)(rintf(temp / f0)) % 2) != 0){
jamie@43 533 num += data[M + n];
jamie@43 534 }
jamie@43 535 else{
jamie@43 536 den += data[M + n];
jamie@43 537 }
jamie@43 538 }
jamie@1 539 }
jamie@1 540
jamie@1 541 *result = num / den;
jamie@25 542
jamie@38 543 return SUCCESS;
jamie@1 544 }
jamie@1 545
jamie@43 546 int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
jamie@1 547
jamie@48 548 int n = N, rv;
jamie@48 549 float sl, g, temp; /* sl = specific loudness */
jamie@48 550
jamie@48 551 sl = g = temp = 0.f;
jamie@48 552
jamie@48 553 if(n > BARK_BANDS)
jamie@48 554 rv = BAD_VECTOR_SIZE;
jamie@48 555 else
jamie@48 556 rv = SUCCESS;
jamie@48 557
jamie@48 558
jamie@48 559 while(n--){
jamie@48 560 sl = pow(data[n], 0.23);
jamie@48 561 g = (n < 15 ? 1.f : 0.066 * exp(0.171 * n));
jamie@49 562 temp += n * g * sl;
jamie@48 563 }
jamie@48 564
jamie@48 565 *result = 0.11 * temp / N;
jamie@48 566
jamie@48 567 return rv;
jamie@25 568
jamie@1 569 }
jamie@1 570
jamie@52 571 int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result){
jamie@1 572
jamie@48 573 const float *freqs, *amps;
jamie@48 574 float f, a,
jamie@48 575 F, A, FA, FSQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@48 576 int n, M;
jamie@48 577
jamie@48 578 F = A = FA = FSQ = 0.f;
jamie@48 579 n = M = N >> 1;
jamie@48 580
jamie@52 581 amps = data;
jamie@52 582 freqs = data + n;
jamie@48 583
jamie@48 584 while(n--){
jamie@48 585 f = freqs[n];
jamie@48 586 a = amps[n];
jamie@48 587 F += f;
jamie@48 588 A += a;
jamie@48 589 FA += f * a;
jamie@48 590 FSQ += f * f;
jamie@48 591 }
jamie@48 592
jamie@48 593 *result = (1.f / A) * (M * FA - F * A) / (M * FSQ - F * F);
jamie@48 594
jamie@48 595 return SUCCESS;
jamie@25 596
jamie@1 597 }
jamie@1 598
jamie@45 599 int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){
jamie@25 600
jamie@45 601 int n = N;
jamie@45 602 float temp;
jamie@45 603
jamie@46 604 *result = data[--n];
jamie@45 605
jamie@45 606 while(n--){
jamie@45 607 if((temp = data[n]) > *(float *)argv)
jamie@45 608 *result = MIN(*result, data[n]);
jamie@45 609 }
jamie@45 610
jamie@45 611 return SUCCESS;
jamie@45 612 }
jamie@45 613
jamie@45 614 int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
jamie@45 615
jamie@1 616 int n = N;
jamie@1 617
jamie@46 618 *result = data[--n];
jamie@44 619
jamie@45 620 while(n--)
jamie@45 621 *result = MAX(*result, data[n]);
jamie@44 622
jamie@38 623 return SUCCESS;
jamie@1 624 }
jamie@1 625
jamie@45 626
jamie@45 627 int xtract_sum(const float *data, const int N, const void *argv, float *result){
jamie@45 628
jamie@45 629 int n = N;
jamie@45 630
jamie@45 631 while(n--)
jamie@45 632 *result += *data++;
jamie@45 633
jamie@45 634 return SUCCESS;
jamie@45 635
jamie@45 636 }
jamie@45 637
jamie@43 638 int xtract_hps(const float *data, const int N, const void *argv, float *result){
jamie@1 639
jamie@1 640 int n = N, M, m, l, peak_index, position1_lwr;
jamie@1 641 float *coeffs2, *coeffs3, *product, L,
jamie@25 642 largest1_lwr, peak, ratio1, sr;
jamie@1 643
jamie@25 644 sr = *(float*)argv;
jamie@25 645
jamie@1 646 coeffs2 = (float *)malloc(N * sizeof(float));
jamie@1 647 coeffs3 = (float *)malloc(N * sizeof(float));
jamie@1 648 product = (float *)malloc(N * sizeof(float));
jamie@25 649
jamie@1 650 while(n--) coeffs2[n] = coeffs3[n] = 1;
jamie@1 651
jamie@1 652 M = N >> 1;
jamie@1 653 L = N / 3;
jamie@1 654
jamie@1 655 while(M--){
jamie@25 656 m = M << 1;
jamie@25 657 coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
jamie@1 658
jamie@25 659 if(M < L){
jamie@25 660 l = M * 3;
jamie@25 661 coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3;
jamie@25 662 }
jamie@1 663 }
jamie@25 664
jamie@1 665 peak_index = peak = 0;
jamie@25 666
jamie@1 667 for(n = 1; n < N; n++){
jamie@25 668 product[n] = data[n] * coeffs2[n] * coeffs3[n];
jamie@25 669 if(product[n] > peak){
jamie@25 670 peak_index = n;
jamie@25 671 peak = product[n];
jamie@25 672 }
jamie@1 673 }
jamie@1 674
jamie@1 675 largest1_lwr = position1_lwr = 0;
jamie@1 676
jamie@1 677 for(n = 0; n < N; n++){
jamie@25 678 if(data[n] > largest1_lwr && n != peak_index){
jamie@25 679 largest1_lwr = data[n];
jamie@25 680 position1_lwr = n;
jamie@25 681 }
jamie@1 682 }
jamie@1 683
jamie@1 684 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 685
jamie@1 686 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@25 687 peak_index * 0.6 && ratio1 > 0.1)
jamie@25 688 peak_index = position1_lwr;
jamie@1 689
jamie@22 690 *result = sr / (float)peak_index;
jamie@25 691
jamie@1 692 free(coeffs2);
jamie@1 693 free(coeffs3);
jamie@1 694 free(product);
jamie@25 695
jamie@38 696 return SUCCESS;
jamie@1 697 }
jamie@5 698
jamie@5 699
jamie@43 700 int xtract_f0(const float *data, const int N, const void *argv, float *result){
jamie@5 701
jamie@25 702 int M, sr, tau, n;
jamie@43 703 size_t bytes;
jamie@43 704 float f0, err_tau_1, err_tau_x, array_max,
jamie@43 705 threshold_peak, threshold_centre,
jamie@43 706 *input;
jamie@22 707
jamie@25 708 sr = *(float *)argv;
jamie@43 709
jamie@43 710 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 711 input = memcpy(input, data, bytes);
jamie@25 712 /* threshold_peak = *((float *)argv+1);
jamie@25 713 threshold_centre = *((float *)argv+2);
jamie@25 714 printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
jamie@25 715 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 716
jamie@25 717 /* FIX: tweak and make into macros */
jamie@25 718 threshold_peak = .8;
jamie@25 719 threshold_centre = .3;
jamie@25 720 M = N >> 1;
jamie@25 721 err_tau_1 = 0;
jamie@25 722 array_max = 0;
jamie@25 723
jamie@25 724 /* Find the array max */
jamie@25 725 for(n = 0; n < N; n++){
jamie@43 726 if (input[n] > array_max)
jamie@43 727 array_max = input[n];
jamie@12 728 }
jamie@25 729
jamie@25 730 threshold_peak *= array_max;
jamie@25 731
jamie@25 732 /* peak clip */
jamie@25 733 for(n = 0; n < N; n++){
jamie@43 734 if(input[n] > threshold_peak)
jamie@43 735 input[n] = threshold_peak;
jamie@43 736 else if(input[n] < -threshold_peak)
jamie@43 737 input[n] = -threshold_peak;
jamie@25 738 }
jamie@25 739
jamie@25 740 threshold_centre *= array_max;
jamie@25 741
jamie@25 742 /* Centre clip */
jamie@25 743 for(n = 0; n < N; n++){
jamie@43 744 if (input[n] < threshold_centre)
jamie@43 745 input[n] = 0;
jamie@25 746 else
jamie@43 747 input[n] -= threshold_centre;
jamie@25 748 }
jamie@25 749
jamie@25 750 /* Estimate fundamental freq */
jamie@25 751 for (n = 1; n < M; n++)
jamie@43 752 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@25 753 /* 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 754 for (tau = 2; tau < M; tau++){
jamie@25 755 err_tau_x = 0;
jamie@25 756 for (n = 1; n < M; n++){
jamie@43 757 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@25 758 }
jamie@25 759 if (err_tau_x < err_tau_1) {
jamie@25 760 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@25 761 *result = f0;
jamie@43 762 free(input);
jamie@25 763 return SUCCESS;
jamie@25 764 }
jamie@25 765 }
jamie@43 766 *result = -0;
jamie@43 767 free(input);
jamie@25 768 return NO_RESULT;
jamie@5 769 }
jamie@43 770
jamie@43 771 int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
jamie@44 772
jamie@43 773 float *magnitudes = NULL, argf[2], *peaks = NULL, return_code;
jamie@44 774
jamie@43 775 return_code = xtract_f0(data, N, argv, result);
jamie@44 776
jamie@43 777 if(return_code == NO_RESULT){
jamie@44 778
jamie@43 779 magnitudes = (float *)malloc(N * sizeof(float));
jamie@43 780 peaks = (float *)malloc(N * sizeof(float));
jamie@46 781 xtract_magnitude_spectrum(data, N, argv, magnitudes);
jamie@43 782 argf[0] = 10.f;
jamie@43 783 argf[1] = *(float *)argv;
jamie@52 784 xtract_peak_spectrum(magnitudes, N, argf, peaks);
jamie@43 785 argf[0] = 0.f;
jamie@45 786 xtract_lowest_value(peaks, N >> 1, argf, result);
jamie@44 787
jamie@43 788 free(magnitudes);
jamie@43 789 free(peaks);
jamie@43 790 }
jamie@43 791
jamie@43 792 return SUCCESS;
jamie@43 793
jamie@43 794 }
jamie@44 795