annotate src/scalar.c @ 59:8fd7088c8ff6

Various minor fixes
author Jamie Bullock <jamie@postlude.co.uk>
date Mon, 12 Feb 2007 17:11:31 +0000
parents 450712b21565
children f926b6b299e7
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@1 29
jamie@43 30 int xtract_mean(const float *data, const int N, const void *argv, float *result){
jamie@25 31
jamie@1 32 int n = N;
jamie@1 33
jamie@1 34 while(n--)
jamie@42 35 *result += data[n];
jamie@25 36
jamie@1 37 *result /= N;
jamie@38 38
jamie@56 39 return XTRACT_SUCCESS;
jamie@1 40 }
jamie@1 41
jamie@43 42 int xtract_variance(const float *data, const int N, const void *argv, float *result){
jamie@25 43
jamie@1 44 int n = N;
jamie@1 45
jamie@1 46 while(n--)
jamie@43 47 *result += pow(data[n] - *(float *)argv, 2);
jamie@25 48
jamie@43 49 *result = *result / (N - 1);
jamie@44 50
jamie@56 51 return XTRACT_SUCCESS;
jamie@1 52 }
jamie@1 53
jamie@43 54 int xtract_standard_deviation(const float *data, const int N, const void *argv, float *result){
jamie@25 55
jamie@59 56 //*result = sqrt(*(float *)argv);
jamie@59 57 *result = sqrt(-40.);
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@59 454 //*result = sfmdb;
jamie@25 455
jamie@56 456 return XTRACT_SUCCESS;
jamie@1 457 }
jamie@1 458
jamie@43 459 int xtract_crest(const float *data, const int N, const void *argv, float *result){
jamie@25 460
jamie@45 461 float max, mean;
jamie@45 462
jamie@45 463 max = mean = 0.f;
jamie@45 464
jamie@45 465 max = *(float *)argv;
jamie@45 466 mean = *((float *)argv+1);
jamie@45 467
jamie@45 468 *result = max / mean;
jamie@45 469
jamie@56 470 return XTRACT_SUCCESS;
jamie@25 471
jamie@1 472 }
jamie@1 473
jamie@43 474 int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
jamie@25 475
jamie@45 476 float h, i, p; /*harmonics, inharmonics, partials */
jamie@45 477
jamie@45 478 i = p = h = 0.f;
jamie@45 479
jamie@45 480 h = *(float *)argv;
jamie@45 481 p = *((float *)argv+1);
jamie@45 482
jamie@45 483 i = p - h;
jamie@45 484
jamie@45 485 *result = i / p;
jamie@45 486
jamie@56 487 return XTRACT_SUCCESS;
jamie@25 488
jamie@1 489 }
jamie@2 490
jamie@43 491 int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
jamie@1 492
jamie@1 493 int n = N;
jamie@1 494
jamie@56 495 while(n--) *result += XTRACT_SQ(data[n]);
jamie@1 496
jamie@1 497 *result = sqrt(*result / N);
jamie@25 498
jamie@56 499 return XTRACT_SUCCESS;
jamie@1 500 }
jamie@1 501
jamie@52 502 int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result){
jamie@1 503
jamie@41 504 int n = N >> 1;
jamie@43 505 float num = 0.f, den = 0.f, fund;
jamie@43 506 const float *freqs, *amps;
jamie@1 507
jamie@41 508 fund = *(float *)argv;
jamie@52 509 amps = data;
jamie@52 510 freqs = data + n;
jamie@25 511
jamie@1 512 while(n--){
jamie@59 513 if(amps[n]){
jamie@59 514 num += fabs(freqs[n] - n * fund) * XTRACT_SQ(amps[n]);
jamie@59 515 den += XTRACT_SQ(amps[n]);
jamie@59 516 }
jamie@1 517 }
jamie@1 518
jamie@41 519 *result = (2 * num) / (fund * den);
jamie@25 520
jamie@56 521 return XTRACT_SUCCESS;
jamie@1 522 }
jamie@1 523
jamie@1 524
jamie@43 525 int xtract_power(const float *data, const int N, const void *argv, float *result){
jamie@1 526
jamie@56 527 return XTRACT_FEATURE_NOT_IMPLEMENTED;
jamie@25 528
jamie@1 529 }
jamie@1 530
jamie@43 531 int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
jamie@1 532
jamie@43 533 int M = (N >> 1), n;
jamie@1 534
jamie@59 535 float num = 0.f, den = 0.f, temp;
jamie@44 536
jamie@43 537 for(n = 0; n < M; n++){
jamie@43 538 if((temp = data[n])){
jamie@59 539 if(XTRACT_IS_ODD(n)){
jamie@59 540 num += temp;
jamie@43 541 }
jamie@43 542 else{
jamie@59 543 den += temp;
jamie@43 544 }
jamie@43 545 }
jamie@1 546 }
jamie@1 547
jamie@1 548 *result = num / den;
jamie@25 549
jamie@56 550 return XTRACT_SUCCESS;
jamie@1 551 }
jamie@1 552
jamie@43 553 int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
jamie@1 554
jamie@48 555 int n = N, rv;
jamie@48 556 float sl, g, temp; /* sl = specific loudness */
jamie@48 557
jamie@48 558 sl = g = temp = 0.f;
jamie@48 559
jamie@56 560 if(n > XTRACT_BARK_BANDS)
jamie@56 561 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 562 else
jamie@56 563 rv = XTRACT_SUCCESS;
jamie@48 564
jamie@48 565
jamie@48 566 while(n--){
jamie@59 567 sl = powf(data[n], 0.23);
jamie@59 568 g = (n < 15 ? 1.f : 0.066 * expf(0.171 * n));
jamie@49 569 temp += n * g * sl;
jamie@48 570 }
jamie@48 571
jamie@48 572 *result = 0.11 * temp / N;
jamie@48 573
jamie@48 574 return rv;
jamie@25 575
jamie@1 576 }
jamie@1 577
jamie@52 578 int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result){
jamie@1 579
jamie@48 580 const float *freqs, *amps;
jamie@48 581 float f, a,
jamie@56 582 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@48 583 int n, M;
jamie@48 584
jamie@56 585 F = A = FA = FXTRACT_SQ = 0.f;
jamie@48 586 n = M = N >> 1;
jamie@48 587
jamie@52 588 amps = data;
jamie@52 589 freqs = data + n;
jamie@48 590
jamie@48 591 while(n--){
jamie@48 592 f = freqs[n];
jamie@48 593 a = amps[n];
jamie@48 594 F += f;
jamie@48 595 A += a;
jamie@48 596 FA += f * a;
jamie@56 597 FXTRACT_SQ += f * f;
jamie@48 598 }
jamie@48 599
jamie@56 600 *result = (1.f / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 601
jamie@56 602 return XTRACT_SUCCESS;
jamie@25 603
jamie@1 604 }
jamie@1 605
jamie@45 606 int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){
jamie@25 607
jamie@45 608 int n = N;
jamie@45 609 float temp;
jamie@45 610
jamie@46 611 *result = data[--n];
jamie@45 612
jamie@45 613 while(n--){
jamie@45 614 if((temp = data[n]) > *(float *)argv)
jamie@56 615 *result = XTRACT_MIN(*result, data[n]);
jamie@45 616 }
jamie@45 617
jamie@56 618 return XTRACT_SUCCESS;
jamie@45 619 }
jamie@45 620
jamie@45 621 int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
jamie@45 622
jamie@1 623 int n = N;
jamie@1 624
jamie@46 625 *result = data[--n];
jamie@44 626
jamie@45 627 while(n--)
jamie@56 628 *result = XTRACT_MAX(*result, data[n]);
jamie@44 629
jamie@56 630 return XTRACT_SUCCESS;
jamie@1 631 }
jamie@1 632
jamie@45 633
jamie@45 634 int xtract_sum(const float *data, const int N, const void *argv, float *result){
jamie@45 635
jamie@45 636 int n = N;
jamie@45 637
jamie@45 638 while(n--)
jamie@45 639 *result += *data++;
jamie@45 640
jamie@56 641 return XTRACT_SUCCESS;
jamie@45 642
jamie@45 643 }
jamie@45 644
jamie@59 645 int xtract_nonzero_count(const float *data, const int N, const void *argv, float *result){
jamie@59 646
jamie@59 647 int n = N;
jamie@59 648
jamie@59 649 while(n--)
jamie@59 650 *result += (*data++ ? 1 : 0);
jamie@59 651
jamie@59 652 return XTRACT_SUCCESS;
jamie@59 653
jamie@59 654 }
jamie@59 655
jamie@43 656 int xtract_hps(const float *data, const int N, const void *argv, float *result){
jamie@1 657
jamie@1 658 int n = N, M, m, l, peak_index, position1_lwr;
jamie@1 659 float *coeffs2, *coeffs3, *product, L,
jamie@25 660 largest1_lwr, peak, ratio1, sr;
jamie@1 661
jamie@25 662 sr = *(float*)argv;
jamie@25 663
jamie@1 664 coeffs2 = (float *)malloc(N * sizeof(float));
jamie@1 665 coeffs3 = (float *)malloc(N * sizeof(float));
jamie@1 666 product = (float *)malloc(N * sizeof(float));
jamie@25 667
jamie@1 668 while(n--) coeffs2[n] = coeffs3[n] = 1;
jamie@1 669
jamie@1 670 M = N >> 1;
jamie@1 671 L = N / 3;
jamie@1 672
jamie@1 673 while(M--){
jamie@25 674 m = M << 1;
jamie@25 675 coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
jamie@1 676
jamie@25 677 if(M < L){
jamie@25 678 l = M * 3;
jamie@25 679 coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3;
jamie@25 680 }
jamie@1 681 }
jamie@25 682
jamie@1 683 peak_index = peak = 0;
jamie@25 684
jamie@1 685 for(n = 1; n < N; n++){
jamie@25 686 product[n] = data[n] * coeffs2[n] * coeffs3[n];
jamie@25 687 if(product[n] > peak){
jamie@25 688 peak_index = n;
jamie@25 689 peak = product[n];
jamie@25 690 }
jamie@1 691 }
jamie@1 692
jamie@1 693 largest1_lwr = position1_lwr = 0;
jamie@1 694
jamie@1 695 for(n = 0; n < N; n++){
jamie@25 696 if(data[n] > largest1_lwr && n != peak_index){
jamie@25 697 largest1_lwr = data[n];
jamie@25 698 position1_lwr = n;
jamie@25 699 }
jamie@1 700 }
jamie@1 701
jamie@1 702 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 703
jamie@1 704 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@25 705 peak_index * 0.6 && ratio1 > 0.1)
jamie@25 706 peak_index = position1_lwr;
jamie@1 707
jamie@22 708 *result = sr / (float)peak_index;
jamie@25 709
jamie@1 710 free(coeffs2);
jamie@1 711 free(coeffs3);
jamie@1 712 free(product);
jamie@25 713
jamie@56 714 return XTRACT_SUCCESS;
jamie@1 715 }
jamie@5 716
jamie@5 717
jamie@43 718 int xtract_f0(const float *data, const int N, const void *argv, float *result){
jamie@5 719
jamie@25 720 int M, sr, tau, n;
jamie@43 721 size_t bytes;
jamie@43 722 float f0, err_tau_1, err_tau_x, array_max,
jamie@43 723 threshold_peak, threshold_centre,
jamie@43 724 *input;
jamie@22 725
jamie@25 726 sr = *(float *)argv;
jamie@43 727
jamie@43 728 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 729 input = memcpy(input, data, bytes);
jamie@25 730 /* threshold_peak = *((float *)argv+1);
jamie@25 731 threshold_centre = *((float *)argv+2);
jamie@25 732 printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
jamie@25 733 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 734
jamie@25 735 /* FIX: tweak and make into macros */
jamie@25 736 threshold_peak = .8;
jamie@25 737 threshold_centre = .3;
jamie@25 738 M = N >> 1;
jamie@25 739 err_tau_1 = 0;
jamie@25 740 array_max = 0;
jamie@25 741
jamie@25 742 /* Find the array max */
jamie@25 743 for(n = 0; n < N; n++){
jamie@43 744 if (input[n] > array_max)
jamie@43 745 array_max = input[n];
jamie@12 746 }
jamie@25 747
jamie@25 748 threshold_peak *= array_max;
jamie@25 749
jamie@25 750 /* peak clip */
jamie@25 751 for(n = 0; n < N; n++){
jamie@43 752 if(input[n] > threshold_peak)
jamie@43 753 input[n] = threshold_peak;
jamie@43 754 else if(input[n] < -threshold_peak)
jamie@43 755 input[n] = -threshold_peak;
jamie@25 756 }
jamie@25 757
jamie@25 758 threshold_centre *= array_max;
jamie@25 759
jamie@25 760 /* Centre clip */
jamie@25 761 for(n = 0; n < N; n++){
jamie@43 762 if (input[n] < threshold_centre)
jamie@43 763 input[n] = 0;
jamie@25 764 else
jamie@43 765 input[n] -= threshold_centre;
jamie@25 766 }
jamie@25 767
jamie@25 768 /* Estimate fundamental freq */
jamie@25 769 for (n = 1; n < M; n++)
jamie@43 770 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@25 771 /* 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 772 for (tau = 2; tau < M; tau++){
jamie@25 773 err_tau_x = 0;
jamie@25 774 for (n = 1; n < M; n++){
jamie@43 775 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@25 776 }
jamie@25 777 if (err_tau_x < err_tau_1) {
jamie@25 778 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@25 779 *result = f0;
jamie@43 780 free(input);
jamie@56 781 return XTRACT_SUCCESS;
jamie@25 782 }
jamie@25 783 }
jamie@43 784 *result = -0;
jamie@43 785 free(input);
jamie@56 786 return XTRACT_NO_RESULT;
jamie@5 787 }
jamie@43 788
jamie@43 789 int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
jamie@44 790
jamie@59 791 float *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 792
jamie@43 793 return_code = xtract_f0(data, N, argv, result);
jamie@44 794
jamie@56 795 if(return_code == XTRACT_NO_RESULT){
jamie@44 796
jamie@59 797 sr = *(float *)argv;
jamie@59 798 spectrum = (float *)malloc(N * sizeof(float));
jamie@43 799 peaks = (float *)malloc(N * sizeof(float));
jamie@59 800 argf[0] = sr;
jamie@59 801 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@59 802 xtract_spectrum(data, N, argf, spectrum);
jamie@59 803 argf[1] = 10.f;
jamie@59 804 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@43 805 argf[0] = 0.f;
jamie@59 806 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 807
jamie@59 808 free(spectrum);
jamie@43 809 free(peaks);
jamie@43 810 }
jamie@43 811
jamie@56 812 return XTRACT_SUCCESS;
jamie@43 813
jamie@43 814 }
jamie@44 815