annotate src/scalar.c @ 115:6c5ece9cba3a

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