annotate src/scalar.c @ 84:7c8edb20f740

Fixed bug in xtract_irregularity_k() - failure to initialise *result to zero
author Dan Stowell <danstowell@gmail.com>
date Sun, 02 Sep 2007 14:28:00 +0000
parents 5fadbacdb2a7
children 89b516adb5df
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;
danstowell@84 234
danstowell@84 235 *result = 0.f;
danstowell@84 236
jamie@1 237 for(n = 1; n < M; n++)
jamie@42 238 *result += fabs(data[n] - (data[n-1] + data[n] + data[n+1]) / 3);
jamie@1 239
jamie@56 240 return XTRACT_SUCCESS;
jamie@1 241 }
jamie@1 242
jamie@43 243 int xtract_irregularity_j(const float *data, const int N, const void *argv, float *result){
jamie@25 244
jamie@1 245 int n = N;
jamie@1 246
jamie@59 247 double num = 0.f, den = 0.f;
jamie@1 248
jamie@1 249 while(n--){
jamie@42 250 num += pow(data[n] - data[n+1], 2);
jamie@42 251 den += pow(data[n], 2);
jamie@1 252 }
jamie@25 253
jamie@59 254 *result = (float)(num / den);
jamie@1 255
jamie@56 256 return XTRACT_SUCCESS;
jamie@1 257 }
jamie@1 258
jamie@43 259 int xtract_tristimulus_1(const float *data, const int N, const void *argv, float *result){
jamie@1 260
jamie@1 261 int n = N;
jamie@1 262
jamie@42 263 float den, p1, temp;
jamie@1 264
jamie@42 265 den = p1 = temp = 0.f;
jamie@1 266
jamie@42 267 for(n = 0; n < N; n++){
jamie@42 268 if((temp = data[n])){
jamie@42 269 den += temp;
jamie@42 270 if(!p1)
jamie@42 271 p1 = temp;
jamie@42 272 }
jamie@42 273 }
jamie@42 274
jamie@42 275 *result = p1 / den;
jamie@1 276
jamie@56 277 return XTRACT_SUCCESS;
jamie@1 278 }
jamie@1 279
jamie@43 280 int xtract_tristimulus_2(const float *data, const int N, const void *argv, float *result){
jamie@25 281
jamie@1 282 int n = N;
jamie@1 283
jamie@42 284 float den, p2, p3, p4, temp;
jamie@1 285
jamie@42 286 den = p2 = p3 = p4 = temp = 0.f;
jamie@1 287
jamie@42 288 for(n = 0; n < N; n++){
jamie@42 289 if((temp = data[n])){
jamie@42 290 den += temp;
jamie@42 291 if(!p2)
jamie@42 292 p2 = temp;
jamie@42 293 else if(!p3)
jamie@42 294 p3 = temp;
jamie@42 295 else if(!p4)
jamie@42 296 p4 = temp;
jamie@42 297 }
jamie@42 298 }
jamie@42 299
jamie@42 300 *result = (p2 + p3 + p4) / den;
jamie@25 301
jamie@56 302 return XTRACT_SUCCESS;
jamie@1 303 }
jamie@1 304
jamie@43 305 int xtract_tristimulus_3(const float *data, const int N, const void *argv, float *result){
jamie@25 306
jamie@42 307 int n = N, count = 0;
jamie@1 308
jamie@42 309 float den, num, temp;
jamie@1 310
jamie@42 311 den = num = temp = 0.f;
jamie@1 312
jamie@42 313 for(n = 0; n < N; n++){
jamie@42 314 if((temp = data[n])){
jamie@42 315 den += temp;
jamie@42 316 if(count >= 5)
jamie@42 317 num += temp;
jamie@42 318 count++;
jamie@42 319 }
jamie@42 320 }
jamie@25 321
jamie@1 322 *result = num / den;
jamie@25 323
jamie@56 324 return XTRACT_SUCCESS;
jamie@1 325 }
jamie@1 326
jamie@43 327 int xtract_smoothness(const float *data, const int N, const void *argv, float *result){
jamie@25 328
jamie@59 329 int n, M;
jamie@1 330
jamie@43 331 float *input;
jamie@43 332
jamie@43 333 input = (float *)malloc(N * sizeof(float));
jamie@59 334 memcpy(input, data, N * sizeof(float));
jamie@43 335
jamie@43 336 if (input[0] <= 0) input[0] = 1;
jamie@25 337
jamie@59 338 M = N - 1;
jamie@59 339
jamie@59 340 for(n = 1; n < M; n++){
jamie@43 341 if(input[n] <= 0) input[n] = 1;
jamie@59 342 *result += fabs(20 * log(input[n]) - (20 * log(input[n-1]) +
jamie@59 343 20 * log(input[n]) + 20 * log(input[n+1])) / 3);
jamie@25 344 }
jamie@43 345
jamie@43 346 free(input);
jamie@44 347
jamie@56 348 return XTRACT_SUCCESS;
jamie@1 349 }
jamie@1 350
jamie@43 351 int xtract_spread(const float *data, const int N, const void *argv, float *result){
jamie@1 352
jamie@1 353 int n = N;
jamie@1 354
jamie@83 355 float num = 0.f, den = 0.f, temp = 0.f;
jamie@83 356
jamie@83 357 if(argv == NULL)
jamie@83 358 return XTRACT_BAD_ARGV;
jamie@1 359
jamie@1 360 while(n--){
jamie@48 361 temp = n - *(float *)argv;
jamie@56 362 num += XTRACT_SQ(temp) * data[n];
jamie@25 363 den += data[n];
jamie@1 364 }
jamie@1 365
jamie@1 366 *result = sqrt(num / den);
jamie@25 367
jamie@56 368 return XTRACT_SUCCESS;
jamie@1 369 }
jamie@1 370
jamie@43 371 int xtract_zcr(const float *data, const int N, const void *argv, float *result){
jamie@1 372
jamie@1 373 int n = N;
jamie@25 374
jamie@1 375 for(n = 1; n < N; n++)
jamie@25 376 if(data[n] * data[n-1] < 0) (*result)++;
jamie@25 377
jamie@1 378 *result /= N;
jamie@25 379
jamie@56 380 return XTRACT_SUCCESS;
jamie@1 381 }
jamie@1 382
jamie@43 383 int xtract_rolloff(const float *data, const int N, const void *argv, float *result){
jamie@1 384
jamie@1 385 int n = N;
jamie@55 386 float pivot, temp, percentile;
jamie@42 387
jamie@42 388 pivot = temp = 0.f;
jamie@55 389 percentile = ((float *)argv)[1];
jamie@25 390
jamie@1 391 while(n--) pivot += data[n];
jamie@25 392
jamie@55 393 pivot *= percentile / 100.f;
jamie@25 394
jamie@42 395 for(n = 0; temp < pivot; n++)
jamie@42 396 temp += data[n];
jamie@1 397
jamie@55 398 *result = n * ((float *)argv)[0];
jamie@55 399 /* *result = (n / (float)N) * (((float *)argv)[1] * .5); */
jamie@25 400
jamie@56 401 return XTRACT_SUCCESS;
jamie@1 402 }
jamie@1 403
jamie@43 404 int xtract_loudness(const float *data, const int N, const void *argv, float *result){
jamie@25 405
jamie@47 406 int n = N, rv;
jamie@25 407
jamie@56 408 if(n > XTRACT_BARK_BANDS)
jamie@56 409 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@47 410 else
jamie@56 411 rv = XTRACT_SUCCESS;
jamie@1 412
jamie@1 413 while(n--)
jamie@59 414 *result += powf(data[n], 0.23);
jamie@38 415
jamie@47 416 return rv;
jamie@1 417 }
jamie@1 418
jamie@43 419 int xtract_flatness(const float *data, const int N, const void *argv, float *result){
jamie@1 420
jamie@42 421 int n;
jamie@1 422
jamie@44 423 double num, den, temp;
jamie@25 424
jamie@44 425 den = data[0];
jamie@44 426 num = (data[0] == 0.f ? 1.f : data[0]);
jamie@43 427
jamie@44 428 for(n = 1; n < N; n++){
jamie@44 429 if((temp = data[n]) != 0.f) {
jamie@44 430 num *= temp;
jamie@44 431 den += temp;
jamie@25 432 }
jamie@1 433 }
jamie@44 434
jamie@59 435 num = powf(num, 1.f / N);
jamie@1 436 den /= N;
jamie@25 437
jamie@56 438 if(num < XTRACT_VERY_SMALL_NUMBER)
jamie@56 439 num = XTRACT_VERY_SMALL_NUMBER;
jamie@44 440
jamie@56 441 if(den < XTRACT_VERY_SMALL_NUMBER)
jamie@56 442 den = XTRACT_VERY_SMALL_NUMBER;
jamie@44 443
jamie@59 444 *result = 10 * log10(num / den);
jamie@25 445
jamie@56 446 return XTRACT_SUCCESS;
jamie@44 447
jamie@1 448 }
jamie@1 449
jamie@43 450 int xtract_tonality(const float *data, const int N, const void *argv, float *result){
jamie@25 451
jamie@1 452 float sfmdb, sfm;
jamie@25 453
jamie@1 454 sfm = *(float *)argv;
jamie@1 455
jamie@59 456 sfmdb = sfm / -60.f;
jamie@25 457
jamie@56 458 *result = XTRACT_MIN(sfmdb, 1);
jamie@25 459
jamie@56 460 return XTRACT_SUCCESS;
jamie@1 461 }
jamie@1 462
jamie@43 463 int xtract_crest(const float *data, const int N, const void *argv, float *result){
jamie@25 464
jamie@45 465 float max, mean;
jamie@45 466
jamie@45 467 max = mean = 0.f;
jamie@45 468
jamie@45 469 max = *(float *)argv;
jamie@45 470 mean = *((float *)argv+1);
jamie@45 471
jamie@45 472 *result = max / mean;
jamie@45 473
jamie@56 474 return XTRACT_SUCCESS;
jamie@25 475
jamie@1 476 }
jamie@1 477
jamie@43 478 int xtract_noisiness(const float *data, const int N, const void *argv, float *result){
jamie@25 479
jamie@45 480 float h, i, p; /*harmonics, inharmonics, partials */
jamie@45 481
jamie@45 482 i = p = h = 0.f;
jamie@45 483
jamie@45 484 h = *(float *)argv;
jamie@45 485 p = *((float *)argv+1);
jamie@45 486
jamie@45 487 i = p - h;
jamie@45 488
jamie@45 489 *result = i / p;
jamie@45 490
jamie@56 491 return XTRACT_SUCCESS;
jamie@25 492
jamie@1 493 }
jamie@2 494
jamie@43 495 int xtract_rms_amplitude(const float *data, const int N, const void *argv, float *result){
jamie@1 496
jamie@1 497 int n = N;
jamie@1 498
jamie@56 499 while(n--) *result += XTRACT_SQ(data[n]);
jamie@1 500
jamie@1 501 *result = sqrt(*result / N);
jamie@25 502
jamie@56 503 return XTRACT_SUCCESS;
jamie@1 504 }
jamie@1 505
jamie@52 506 int xtract_spectral_inharmonicity(const float *data, const int N, const void *argv, float *result){
jamie@1 507
jamie@41 508 int n = N >> 1;
jamie@43 509 float num = 0.f, den = 0.f, fund;
jamie@43 510 const float *freqs, *amps;
jamie@1 511
jamie@41 512 fund = *(float *)argv;
jamie@52 513 amps = data;
jamie@52 514 freqs = data + n;
jamie@25 515
jamie@1 516 while(n--){
jamie@59 517 if(amps[n]){
jamie@59 518 num += fabs(freqs[n] - n * fund) * XTRACT_SQ(amps[n]);
jamie@59 519 den += XTRACT_SQ(amps[n]);
jamie@59 520 }
jamie@1 521 }
jamie@1 522
jamie@41 523 *result = (2 * num) / (fund * den);
jamie@25 524
jamie@56 525 return XTRACT_SUCCESS;
jamie@1 526 }
jamie@1 527
jamie@1 528
jamie@43 529 int xtract_power(const float *data, const int N, const void *argv, float *result){
jamie@1 530
jamie@56 531 return XTRACT_FEATURE_NOT_IMPLEMENTED;
jamie@25 532
jamie@1 533 }
jamie@1 534
jamie@43 535 int xtract_odd_even_ratio(const float *data, const int N, const void *argv, float *result){
jamie@1 536
jamie@43 537 int M = (N >> 1), n;
jamie@1 538
jamie@59 539 float num = 0.f, den = 0.f, temp;
jamie@44 540
jamie@43 541 for(n = 0; n < M; n++){
jamie@43 542 if((temp = data[n])){
jamie@59 543 if(XTRACT_IS_ODD(n)){
jamie@59 544 num += temp;
jamie@43 545 }
jamie@43 546 else{
jamie@59 547 den += temp;
jamie@43 548 }
jamie@43 549 }
jamie@1 550 }
jamie@1 551
jamie@1 552 *result = num / den;
jamie@25 553
jamie@56 554 return XTRACT_SUCCESS;
jamie@1 555 }
jamie@1 556
jamie@43 557 int xtract_sharpness(const float *data, const int N, const void *argv, float *result){
jamie@1 558
jamie@48 559 int n = N, rv;
jamie@48 560 float sl, g, temp; /* sl = specific loudness */
jamie@48 561
jamie@48 562 sl = g = temp = 0.f;
jamie@48 563
jamie@56 564 if(n > XTRACT_BARK_BANDS)
jamie@56 565 rv = XTRACT_BAD_VECTOR_SIZE;
jamie@48 566 else
jamie@56 567 rv = XTRACT_SUCCESS;
jamie@48 568
jamie@48 569
jamie@48 570 while(n--){
jamie@59 571 sl = powf(data[n], 0.23);
jamie@59 572 g = (n < 15 ? 1.f : 0.066 * expf(0.171 * n));
jamie@49 573 temp += n * g * sl;
jamie@48 574 }
jamie@48 575
jamie@48 576 *result = 0.11 * temp / N;
jamie@48 577
jamie@48 578 return rv;
jamie@25 579
jamie@1 580 }
jamie@1 581
jamie@52 582 int xtract_spectral_slope(const float *data, const int N, const void *argv, float *result){
jamie@1 583
jamie@48 584 const float *freqs, *amps;
jamie@48 585 float f, a,
jamie@56 586 F, A, FA, FXTRACT_SQ; /* sums of freqs, amps, freq * amps, freq squared */
jamie@48 587 int n, M;
jamie@48 588
jamie@56 589 F = A = FA = FXTRACT_SQ = 0.f;
jamie@48 590 n = M = N >> 1;
jamie@48 591
jamie@52 592 amps = data;
jamie@52 593 freqs = data + n;
jamie@48 594
jamie@48 595 while(n--){
jamie@48 596 f = freqs[n];
jamie@48 597 a = amps[n];
jamie@48 598 F += f;
jamie@48 599 A += a;
jamie@48 600 FA += f * a;
jamie@56 601 FXTRACT_SQ += f * f;
jamie@48 602 }
jamie@48 603
jamie@56 604 *result = (1.f / A) * (M * FA - F * A) / (M * FXTRACT_SQ - F * F);
jamie@48 605
jamie@56 606 return XTRACT_SUCCESS;
jamie@25 607
jamie@1 608 }
jamie@1 609
jamie@45 610 int xtract_lowest_value(const float *data, const int N, const void *argv, float *result){
jamie@25 611
jamie@45 612 int n = N;
jamie@45 613 float temp;
jamie@45 614
jamie@46 615 *result = data[--n];
jamie@45 616
jamie@45 617 while(n--){
jamie@45 618 if((temp = data[n]) > *(float *)argv)
jamie@56 619 *result = XTRACT_MIN(*result, data[n]);
jamie@45 620 }
jamie@45 621
jamie@56 622 return XTRACT_SUCCESS;
jamie@45 623 }
jamie@45 624
jamie@45 625 int xtract_highest_value(const float *data, const int N, const void *argv, float *result){
jamie@45 626
jamie@1 627 int n = N;
jamie@1 628
jamie@46 629 *result = data[--n];
jamie@44 630
jamie@45 631 while(n--)
jamie@56 632 *result = XTRACT_MAX(*result, data[n]);
jamie@44 633
jamie@56 634 return XTRACT_SUCCESS;
jamie@1 635 }
jamie@1 636
jamie@45 637
jamie@45 638 int xtract_sum(const float *data, const int N, const void *argv, float *result){
jamie@45 639
jamie@45 640 int n = N;
jamie@45 641
jamie@45 642 while(n--)
jamie@45 643 *result += *data++;
jamie@45 644
jamie@56 645 return XTRACT_SUCCESS;
jamie@45 646
jamie@45 647 }
jamie@45 648
jamie@59 649 int xtract_nonzero_count(const float *data, const int N, const void *argv, float *result){
jamie@59 650
jamie@59 651 int n = N;
jamie@59 652
jamie@59 653 while(n--)
jamie@59 654 *result += (*data++ ? 1 : 0);
jamie@59 655
jamie@59 656 return XTRACT_SUCCESS;
jamie@59 657
jamie@59 658 }
jamie@59 659
jamie@43 660 int xtract_hps(const float *data, const int N, const void *argv, float *result){
jamie@1 661
jamie@1 662 int n = N, M, m, l, peak_index, position1_lwr;
jamie@1 663 float *coeffs2, *coeffs3, *product, L,
jamie@25 664 largest1_lwr, peak, ratio1, sr;
jamie@1 665
jamie@25 666 sr = *(float*)argv;
jamie@78 667 if(sr == 0)
jamie@78 668 sr = 44100.f;
jamie@25 669
jamie@1 670 coeffs2 = (float *)malloc(N * sizeof(float));
jamie@1 671 coeffs3 = (float *)malloc(N * sizeof(float));
jamie@1 672 product = (float *)malloc(N * sizeof(float));
jamie@25 673
jamie@1 674 while(n--) coeffs2[n] = coeffs3[n] = 1;
jamie@1 675
jamie@1 676 M = N >> 1;
jamie@1 677 L = N / 3;
jamie@1 678
jamie@1 679 while(M--){
jamie@25 680 m = M << 1;
jamie@25 681 coeffs2[M] = (data[m] + data[m+1]) * 0.5f;
jamie@1 682
jamie@25 683 if(M < L){
jamie@25 684 l = M * 3;
jamie@25 685 coeffs3[M] = (data[l] + data[l+1] + data[l+2]) / 3;
jamie@25 686 }
jamie@1 687 }
jamie@25 688
jamie@1 689 peak_index = peak = 0;
jamie@25 690
jamie@1 691 for(n = 1; n < N; n++){
jamie@25 692 product[n] = data[n] * coeffs2[n] * coeffs3[n];
jamie@25 693 if(product[n] > peak){
jamie@25 694 peak_index = n;
jamie@25 695 peak = product[n];
jamie@25 696 }
jamie@1 697 }
jamie@1 698
jamie@1 699 largest1_lwr = position1_lwr = 0;
jamie@1 700
jamie@1 701 for(n = 0; n < N; n++){
jamie@25 702 if(data[n] > largest1_lwr && n != peak_index){
jamie@25 703 largest1_lwr = data[n];
jamie@25 704 position1_lwr = n;
jamie@25 705 }
jamie@1 706 }
jamie@1 707
jamie@1 708 ratio1 = data[position1_lwr] / data[peak_index];
jamie@1 709
jamie@1 710 if(position1_lwr > peak_index * 0.4 && position1_lwr <
jamie@25 711 peak_index * 0.6 && ratio1 > 0.1)
jamie@25 712 peak_index = position1_lwr;
jamie@1 713
jamie@22 714 *result = sr / (float)peak_index;
jamie@25 715
jamie@1 716 free(coeffs2);
jamie@1 717 free(coeffs3);
jamie@1 718 free(product);
jamie@25 719
jamie@56 720 return XTRACT_SUCCESS;
jamie@1 721 }
jamie@5 722
jamie@5 723
jamie@43 724 int xtract_f0(const float *data, const int N, const void *argv, float *result){
jamie@5 725
jamie@78 726 int M, tau, n;
jamie@78 727 float sr;
jamie@43 728 size_t bytes;
jamie@43 729 float f0, err_tau_1, err_tau_x, array_max,
jamie@43 730 threshold_peak, threshold_centre,
jamie@43 731 *input;
jamie@22 732
jamie@25 733 sr = *(float *)argv;
jamie@78 734 if(sr == 0)
jamie@78 735 sr = 44100.f;
jamie@43 736
jamie@43 737 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 738 input = memcpy(input, data, bytes);
jamie@25 739 /* threshold_peak = *((float *)argv+1);
jamie@25 740 threshold_centre = *((float *)argv+2);
jamie@25 741 printf("peak: %.2f\tcentre: %.2f\n", threshold_peak, threshold_centre);*/
jamie@25 742 /* add temporary dynamic control over thresholds to test clipping effects */
jamie@22 743
jamie@25 744 /* FIX: tweak and make into macros */
jamie@25 745 threshold_peak = .8;
jamie@25 746 threshold_centre = .3;
jamie@25 747 M = N >> 1;
jamie@25 748 err_tau_1 = 0;
jamie@25 749 array_max = 0;
jamie@25 750
jamie@25 751 /* Find the array max */
jamie@25 752 for(n = 0; n < N; n++){
jamie@43 753 if (input[n] > array_max)
jamie@43 754 array_max = input[n];
jamie@12 755 }
jamie@25 756
jamie@25 757 threshold_peak *= array_max;
jamie@25 758
jamie@25 759 /* peak clip */
jamie@25 760 for(n = 0; n < N; n++){
jamie@43 761 if(input[n] > threshold_peak)
jamie@43 762 input[n] = threshold_peak;
jamie@43 763 else if(input[n] < -threshold_peak)
jamie@43 764 input[n] = -threshold_peak;
jamie@25 765 }
jamie@25 766
jamie@25 767 threshold_centre *= array_max;
jamie@25 768
jamie@25 769 /* Centre clip */
jamie@25 770 for(n = 0; n < N; n++){
jamie@43 771 if (input[n] < threshold_centre)
jamie@43 772 input[n] = 0;
jamie@25 773 else
jamie@43 774 input[n] -= threshold_centre;
jamie@25 775 }
jamie@25 776
jamie@25 777 /* Estimate fundamental freq */
jamie@25 778 for (n = 1; n < M; n++)
jamie@43 779 err_tau_1 = err_tau_1 + fabs(input[n] - input[n+1]);
jamie@25 780 /* 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 781 for (tau = 2; tau < M; tau++){
jamie@25 782 err_tau_x = 0;
jamie@25 783 for (n = 1; n < M; n++){
jamie@43 784 err_tau_x = err_tau_x + fabs(input[n] - input[n+tau]);
jamie@25 785 }
jamie@25 786 if (err_tau_x < err_tau_1) {
jamie@25 787 f0 = sr / (tau + (err_tau_x / err_tau_1));
jamie@25 788 *result = f0;
jamie@43 789 free(input);
jamie@56 790 return XTRACT_SUCCESS;
jamie@25 791 }
jamie@25 792 }
jamie@43 793 *result = -0;
jamie@43 794 free(input);
jamie@56 795 return XTRACT_NO_RESULT;
jamie@5 796 }
jamie@43 797
jamie@43 798 int xtract_failsafe_f0(const float *data, const int N, const void *argv, float *result){
jamie@44 799
jamie@59 800 float *spectrum = NULL, argf[2], *peaks = NULL, return_code, sr;
jamie@44 801
jamie@43 802 return_code = xtract_f0(data, N, argv, result);
jamie@44 803
jamie@56 804 if(return_code == XTRACT_NO_RESULT){
jamie@44 805
jamie@59 806 sr = *(float *)argv;
jamie@78 807 if(sr == 0)
jamie@78 808 sr = 44100.f;
jamie@59 809 spectrum = (float *)malloc(N * sizeof(float));
jamie@43 810 peaks = (float *)malloc(N * sizeof(float));
jamie@59 811 argf[0] = sr;
jamie@59 812 argf[1] = XTRACT_MAGNITUDE_SPECTRUM;
jamie@59 813 xtract_spectrum(data, N, argf, spectrum);
jamie@59 814 argf[1] = 10.f;
jamie@59 815 xtract_peak_spectrum(spectrum, N >> 1, argf, peaks);
jamie@43 816 argf[0] = 0.f;
jamie@59 817 xtract_lowest_value(peaks+(N >> 1), N >> 1, argf, result);
jamie@44 818
jamie@59 819 free(spectrum);
jamie@43 820 free(peaks);
jamie@43 821 }
jamie@43 822
jamie@56 823 return XTRACT_SUCCESS;
jamie@43 824
jamie@43 825 }
jamie@44 826