annotate src/vector.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 f913cf823628
children 757e6f99dcd7
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_vector.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@43 27 #include <string.h>
jamie@43 28 #include <stdlib.h>
jamie@30 29
jamie@85 30 #ifndef roundf
jamie@85 31 float roundf(float f){
jamie@85 32 if (f - (int)f >= 0.5)
jamie@85 33 return (float)((int)f + 1);
jamie@85 34 else
jamie@85 35 return (float)((int)f);
jamie@85 36 }
jamie@85 37 #endif
jamie@85 38
jamie@30 39 #ifdef XTRACT_FFT
jamie@30 40
jamie@1 41 #include <fftw3.h>
jamie@1 42
jamie@54 43 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 44
jamie@56 45 float *input, *rfft, q, temp;
jamie@43 46 size_t bytes;
jamie@70 47 int n , NxN, M, vector, withDC;
jamie@1 48 fftwf_plan plan;
jamie@1 49
jamie@54 50 M = N >> 1;
jamie@56 51 NxN = XTRACT_SQ(N);
jamie@70 52 withDC = 0;
jamie@54 53
jamie@54 54 rfft = (float *)fftwf_malloc(N * sizeof(float));
jamie@43 55 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 56 input = memcpy(input, data, bytes);
jamie@1 57
jamie@56 58 q = *(float *)argv;
jamie@54 59 vector = (int)*((float *)argv+1);
jamie@70 60 withDC = (int)*((float *)argv+2);
jamie@46 61
jamie@56 62 XTRACT_CHECK_q;
jamie@46 63
jamie@54 64 plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 65
jamie@1 66 fftwf_execute(plan);
jamie@54 67
jamie@54 68 switch(vector){
jamie@67 69
jamie@56 70 case XTRACT_LOG_MAGNITUDE_SPECTRUM:
jamie@67 71 for(n = 1; n < M; n++){
jamie@67 72 if ((temp = XTRACT_SQ(rfft[n]) +
jamie@70 73 XTRACT_SQ(rfft[N - n])) > XTRACT_LOG_LIMIT)
jamie@54 74 temp = log(sqrt(temp) / N);
jamie@54 75 else
jamie@56 76 temp = XTRACT_LOG_LIMIT_DB;
jamie@70 77 if(withDC) {
jamie@70 78 result[n] =
jamie@70 79 /*Normalise*/
jamie@70 80 (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 81 XTRACT_DB_SCALE_OFFSET;
jamie@70 82 result[M + n + 1] = n * q;
jamie@70 83 }
jamie@70 84 else {
jamie@70 85 result[n - 1] =
jamie@70 86 (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 87 XTRACT_DB_SCALE_OFFSET;
jamie@70 88 result[M + n - 1] = n * q;
jamie@70 89 }
jamie@54 90 }
jamie@54 91 break;
jamie@67 92
jamie@56 93 case XTRACT_POWER_SPECTRUM:
jamie@67 94 for(n = 1; n < M; n++){
jamie@70 95 if(withDC){
jamie@70 96 result[n] = (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n]))
jamie@70 97 / NxN;
jamie@70 98 result[M + n + 1] = n * q;
jamie@70 99 }
jamie@70 100 else {
jamie@70 101 result[n - 1] =
jamie@70 102 (XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) / NxN;
jamie@70 103 result[M + n - 1] = n * q;
jamie@70 104 }
jamie@54 105 }
jamie@54 106 break;
jamie@67 107
jamie@56 108 case XTRACT_LOG_POWER_SPECTRUM:
jamie@67 109 for(n = 1; n < M; n++){
jamie@70 110 if ((temp = XTRACT_SQ(rfft[n]) + XTRACT_SQ(rfft[N - n])) >
jamie@67 111 XTRACT_LOG_LIMIT)
jamie@54 112 temp = log(temp / NxN);
jamie@54 113 else
jamie@56 114 temp = XTRACT_LOG_LIMIT_DB;
jamie@70 115 if(withDC){
jamie@70 116 result[n] = (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 117 XTRACT_DB_SCALE_OFFSET;
jamie@70 118 result[M + n + 1] = n * q;
jamie@70 119 }
jamie@70 120 else {
jamie@70 121 result[n - 1] = (temp + XTRACT_DB_SCALE_OFFSET) /
jamie@70 122 XTRACT_DB_SCALE_OFFSET;
jamie@70 123 result[M + n - 1] = n * q;
jamie@70 124 }
jamie@54 125 }
jamie@54 126 break;
jamie@67 127
jamie@54 128 default:
jamie@54 129 /* MAGNITUDE_SPECTRUM */
jamie@67 130 for(n = 1; n < M; n++){
jamie@70 131 if(withDC){
jamie@70 132 result[n] = sqrt(XTRACT_SQ(rfft[n]) +
jamie@70 133 XTRACT_SQ(rfft[N - n])) / N;
jamie@70 134 result[M + n + 1] = n * q;
jamie@70 135 }
jamie@70 136 else {
jamie@70 137 result[n - 1] = sqrt(XTRACT_SQ(rfft[n]) +
jamie@70 138 XTRACT_SQ(rfft[N - n])) / N;
jamie@70 139 result[M + n - 1] = n * q;
jamie@70 140 }
jamie@54 141 }
jamie@54 142 break;
jamie@1 143 }
jamie@1 144
jamie@70 145 if(withDC){
jamie@70 146 /* The DC component */
jamie@70 147 result[0] = XTRACT_SQ(rfft[0]);
jamie@70 148 result[M + 1] = 0.f;
jamie@70 149 /* The Nyquist */
jamie@70 150 result[M] = XTRACT_SQ(rfft[M]);
jamie@70 151 result[N + 1] = q * M;
jamie@70 152 }
jamie@70 153 else {
jamie@70 154 /* The Nyquist */
jamie@70 155 result[M - 1] = XTRACT_SQ(rfft[M]);
jamie@70 156 result[N - 1] = q * M;
jamie@70 157 }
jamie@1 158
jamie@1 159 fftwf_destroy_plan(plan);
jamie@54 160 fftwf_free(rfft);
jamie@43 161 free(input);
jamie@1 162
jamie@56 163 return XTRACT_SUCCESS;
jamie@1 164 }
jamie@1 165
jamie@43 166 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@1 167
jamie@75 168 float *freq, *time;
jamie@75 169 int n, M;
jamie@1 170 fftwf_plan plan;
jamie@1 171
jamie@75 172 M = N << 1;
jamie@43 173
jamie@75 174 freq = (float *)fftwf_malloc(M * sizeof(float));
jamie@75 175 /* Zero pad the input vector */
jamie@75 176 time = (float *)calloc(M, sizeof(float));
jamie@75 177 time = memcpy(time, data, N * sizeof(float));
jamie@75 178
jamie@75 179 plan = fftwf_plan_r2r_1d(M, time, freq, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 180
jamie@1 181 fftwf_execute(plan);
jamie@75 182
jamie@76 183 for(n = 1; n < N; n++){
jamie@75 184 freq[n] = XTRACT_SQ(freq[n]) + XTRACT_SQ(freq[M - n]);
jamie@75 185 freq[M - n] = 0.f;
jamie@75 186 }
jamie@1 187
jamie@75 188 freq[0] = XTRACT_SQ(freq[0]);
jamie@75 189 freq[N] = XTRACT_SQ(freq[N]);
jamie@75 190
jamie@75 191 plan = fftwf_plan_r2r_1d(M, freq, time, FFTW_HC2R, FFTW_ESTIMATE);
jamie@75 192
jamie@75 193 fftwf_execute(plan);
jamie@75 194
jamie@75 195 /* Normalisation factor */
jamie@75 196 M = M * N;
jamie@75 197
jamie@75 198 for(n = 0; n < N; n++)
jamie@75 199 result[n] = time[n] / (float)M;
jamie@75 200 /* result[n] = time[n+1] / (float)M; */
jamie@75 201
jamie@1 202 fftwf_destroy_plan(plan);
jamie@75 203 fftwf_free(freq);
jamie@75 204 free(time);
jamie@38 205
jamie@56 206 return XTRACT_SUCCESS;
jamie@1 207 }
jamie@1 208
jamie@43 209 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 210
jamie@30 211 xtract_mel_filter *f;
jamie@30 212 int n, filter;
jamie@30 213
jamie@30 214 f = (xtract_mel_filter *)argv;
jamie@39 215
jamie@30 216 for(filter = 0; filter < f->n_filters; filter++){
danstowell@68 217 result[filter] = 0.f;
jamie@30 218 for(n = 0; n < N; n++){
jamie@71 219 result[filter] += data[n] * f->filters[filter][n];
jamie@30 220 }
danstowell@69 221 result[filter] = log(result[filter] < XTRACT_LOG_LIMIT ? XTRACT_LOG_LIMIT : result[filter]);
jamie@30 222 }
jamie@30 223
jamie@30 224 for(n = filter + 1; n < N; n++) result[n] = 0;
jamie@30 225
jamie@30 226 xtract_dct(result, f->n_filters, NULL, result);
jamie@43 227
jamie@56 228 return XTRACT_SUCCESS;
jamie@30 229 }
jamie@30 230
jamie@43 231 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 232
jamie@30 233 fftwf_plan plan;
jamie@43 234
jamie@30 235 plan =
danstowell@74 236 fftwf_plan_r2r_1d(N, (float *) data, result, FFTW_REDFT00, FFTW_ESTIMATE);
jamie@30 237
jamie@30 238 fftwf_execute(plan);
jamie@30 239 fftwf_destroy_plan(plan);
jamie@38 240
jamie@56 241 return XTRACT_SUCCESS;
jamie@30 242 }
jamie@30 243
jamie@30 244 #else
jamie@30 245
jamie@67 246 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@30 247
danstowell@66 248 XTRACT_NEEDS_FFTW;
danstowell@66 249 return XTRACT_NO_RESULT;
jamie@30 250
jamie@30 251 }
jamie@30 252
jamie@43 253 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@30 254
danstowell@66 255 XTRACT_NEEDS_FFTW;
danstowell@66 256 return XTRACT_NO_RESULT;
jamie@30 257
jamie@30 258 }
jamie@30 259
jamie@43 260 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 261
danstowell@66 262 XTRACT_NEEDS_FFTW;
danstowell@66 263 return XTRACT_NO_RESULT;
jamie@30 264
jamie@30 265 }
jamie@30 266
jamie@43 267 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 268
danstowell@66 269 XTRACT_NEEDS_FFTW;
danstowell@66 270 return XTRACT_NO_RESULT;
jamie@30 271
jamie@30 272 }
jamie@30 273
jamie@30 274 #endif
jamie@30 275
jamie@43 276 int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){
jamie@30 277
jamie@30 278 /* Naive time domain implementation */
jamie@30 279
jamie@30 280 int n = N, i;
jamie@30 281
jamie@30 282 float corr;
jamie@30 283
jamie@30 284 while(n--){
jamie@30 285 corr = 0;
jamie@30 286 for(i = 0; i < N - n; i++){
jamie@30 287 corr += data[i] * data[i + n];
jamie@30 288 }
jamie@30 289 result[n] = corr / N;
jamie@30 290 }
jamie@38 291
jamie@56 292 return XTRACT_SUCCESS;
jamie@30 293 }
jamie@30 294
jamie@43 295 int xtract_amdf(const float *data, const int N, const void *argv, float *result){
jamie@1 296
jamie@1 297 int n = N, i;
jamie@1 298
jamie@6 299 float md, temp;
jamie@1 300
jamie@1 301 while(n--){
jamie@1 302 md = 0;
jamie@1 303 for(i = 0; i < N - n; i++){
jamie@6 304 temp = data[i] - data[i + n];
jamie@6 305 temp = (temp < 0 ? -temp : temp);
jamie@6 306 md += temp;
jamie@1 307 }
jamie@1 308 result[n] = md / N;
jamie@1 309 }
jamie@38 310
jamie@56 311 return XTRACT_SUCCESS;
jamie@1 312 }
jamie@1 313
jamie@43 314 int xtract_asdf(const float *data, const int N, const void *argv, float *result){
jamie@1 315
jamie@1 316 int n = N, i;
jamie@1 317
jamie@1 318 float sd;
jamie@1 319
jamie@1 320 while(n--){
jamie@1 321 sd = 0;
jamie@1 322 for(i = 0; i < N - n; i++){
jamie@6 323 /*sd = 1;*/
jamie@56 324 sd += XTRACT_SQ(data[i] - data[i + n]);
jamie@1 325 }
jamie@1 326 result[n] = sd / N;
jamie@1 327 }
jamie@38 328
jamie@56 329 return XTRACT_SUCCESS;
jamie@1 330 }
jamie@1 331
jamie@43 332 int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
jamie@1 333
jamie@1 334 int *limits, band, n;
jamie@1 335
jamie@1 336 limits = (int *)argv;
jamie@1 337
jamie@59 338 for(band = 0; band < XTRACT_BARK_BANDS - 1; band++){
jamie@1 339 for(n = limits[band]; n < limits[band + 1]; n++)
jamie@1 340 result[band] += data[n];
jamie@1 341 }
jamie@38 342
jamie@56 343 return XTRACT_SUCCESS;
jamie@1 344 }
jamie@1 345
jamie@52 346 int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 347
jamie@56 348 float threshold, max, y, y2, y3, p, q, *input = NULL;
jamie@43 349 size_t bytes;
jamie@59 350 int n = N, rv = XTRACT_SUCCESS;
jamie@49 351
jamie@56 352 threshold = max = y = y2 = y3 = p = q = 0.f;
jamie@1 353
jamie@1 354 if(argv != NULL){
jamie@56 355 q = ((float *)argv)[0];
jamie@55 356 threshold = ((float *)argv)[1];
jamie@1 357 }
jamie@49 358 else
jamie@56 359 rv = XTRACT_BAD_ARGV;
jamie@49 360
jamie@55 361 if(threshold < 0 || threshold > 100){
jamie@55 362 threshold = 0;
jamie@56 363 rv = XTRACT_BAD_ARGV;
jamie@1 364 }
jamie@1 365
jamie@56 366 XTRACT_CHECK_q;
jamie@49 367
jamie@43 368 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 369
jamie@43 370 if(input != NULL)
jamie@43 371 input = memcpy(input, data, bytes);
jamie@43 372 else
jamie@56 373 return XTRACT_MALLOC_FAILED;
jamie@43 374
jamie@45 375 while(n--)
jamie@56 376 max = XTRACT_MAX(max, input[n]);
jamie@1 377
jamie@55 378 threshold *= .01 * max;
jamie@1 379
jamie@1 380 result[0] = 0;
jamie@59 381 result[N] = 0;
jamie@1 382
jamie@59 383 for(n = 1; n < N; n++){
jamie@55 384 if(input[n] >= threshold){
jamie@43 385 if(input[n] > input[n - 1] && input[n] > input[n + 1]){
jamie@59 386 result[N + n] = q * (n + (p = .5 * (y = input[n-1] -
jamie@52 387 (y3 = input[n+1])) / (input[n - 1] - 2 *
jamie@52 388 (y2 = input[n]) + input[n + 1])));
jamie@52 389 result[n] = y2 - .25 * (y - y3) * p;
jamie@1 390 }
jamie@1 391 else{
jamie@1 392 result[n] = 0;
jamie@59 393 result[N + n] = 0;
jamie@1 394 }
jamie@1 395 }
jamie@1 396 else{
jamie@1 397 result[n] = 0;
jamie@59 398 result[N + n] = 0;
jamie@1 399 }
jamie@1 400 }
jamie@1 401
jamie@43 402 free(input);
jamie@56 403 return (rv ? rv : XTRACT_SUCCESS);
jamie@1 404 }
jamie@41 405
jamie@52 406 int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@38 407
jamie@38 408 int n = (N >> 1), M = n;
jamie@38 409
jamie@43 410 const float *freqs, *amps;
jamie@55 411 float f0, threshold, ratio, nearest, distance;
jamie@38 412
jamie@52 413 amps = data;
jamie@52 414 freqs = data + n;
jamie@38 415 f0 = *((float *)argv);
jamie@55 416 threshold = *((float *)argv+1);
jamie@38 417
jamie@38 418 ratio = nearest = distance = 0.f;
jamie@38 419
jamie@38 420 while(n--){
jamie@38 421 if(freqs[n]){
jamie@38 422 ratio = freqs[n] / f0;
jamie@85 423 nearest = roundf(ratio);
jamie@38 424 distance = fabs(nearest - ratio);
jamie@55 425 if(distance > threshold)
jamie@38 426 result[n] = result[M + n] = 0.f;
jamie@42 427 else {
jamie@52 428 result[n] = amps[n];
jamie@52 429 result[M + n] = freqs[n];
jamie@42 430 }
jamie@38 431 }
jamie@38 432 else
jamie@38 433 result[n] = result[M + n] = 0.f;
jamie@38 434 }
jamie@56 435 return XTRACT_SUCCESS;
jamie@38 436 }
jamie@38 437