annotate src/scalar.c @ 78:afb298ce1b4d

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