annotate src/scalar.c @ 85:89b516adb5df

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