annotate src/scalar.c @ 123:efb1c1ae2ba8

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