annotate src/vector.c @ 55:4ea1a8838b14

Finished the essentials of descriptors.c
author Jamie Bullock <jamie@postlude.co.uk>
date Sun, 21 Jan 2007 14:40:23 +0000
parents 9762d7e3d129
children 450712b21565
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@1 25 #include <math.h>
jamie@43 26 #include <string.h>
jamie@43 27 #include <stdlib.h>
jamie@30 28
jamie@30 29 #ifdef XTRACT_FFT
jamie@30 30
jamie@1 31 #include <fftw3.h>
jamie@1 32
jamie@54 33 int xtract_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 34
jamie@55 35 float *input, *rfft, nyquist, temp;
jamie@43 36 size_t bytes;
jamie@54 37 int n , NxN, M, vector;
jamie@1 38 fftwf_plan plan;
jamie@1 39
jamie@54 40 M = N >> 1;
jamie@54 41 NxN = SQ(N);
jamie@54 42
jamie@54 43 rfft = (float *)fftwf_malloc(N * sizeof(float));
jamie@43 44 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 45 input = memcpy(input, data, bytes);
jamie@1 46
jamie@55 47 nyquist = *(float *)argv;
jamie@54 48 vector = (int)*((float *)argv+1);
jamie@46 49
jamie@55 50 CHECK_nyquist;
jamie@46 51
jamie@54 52 plan = fftwf_plan_r2r_1d(N, input, rfft, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 53
jamie@1 54 fftwf_execute(plan);
jamie@54 55
jamie@54 56 switch(vector){
jamie@54 57 case MAGNITUDE_SPECTRUM:
jamie@54 58 for(n = 0; n < M; n++){
jamie@54 59 result[n] = sqrt(SQ(rfft[n]) + SQ(rfft[N - n])) / N;
jamie@55 60 result[M + n] = n * nyquist;
jamie@54 61 }
jamie@54 62 break;
jamie@54 63 case LOG_MAGNITUDE_SPECTRUM:
jamie@54 64 for(n = 0; n < M; n++){
jamie@54 65 if ((temp = SQ(rfft[n]) + SQ(rfft[N - n])) > LOG_LIMIT)
jamie@54 66 temp = log(sqrt(temp) / N);
jamie@54 67 else
jamie@54 68 temp = LOG_LIMIT_DB;
jamie@54 69 /*Normalise*/
jamie@54 70 result[n] = (temp + DB_SCALE_OFFSET) / DB_SCALE_OFFSET;
jamie@55 71 result[M + n] = n * nyquist;
jamie@54 72 }
jamie@54 73 break;
jamie@54 74 case POWER_SPECTRUM:
jamie@54 75 for(n = 0; n < M; n++){
jamie@54 76 result[n] = (SQ(rfft[n]) + SQ(rfft[N - n])) / NxN;
jamie@55 77 result[M + n] = n * nyquist;
jamie@54 78 }
jamie@54 79 break;
jamie@54 80 case LOG_POWER_SPECTRUM:
jamie@54 81 for(n = 0; n < M; n++){
jamie@54 82 if ((temp = SQ(rfft[n]) + SQ(rfft[N - n])) > LOG_LIMIT)
jamie@54 83 temp = log(temp / NxN);
jamie@54 84 else
jamie@54 85 temp = LOG_LIMIT_DB;
jamie@54 86 result[n] = (temp + DB_SCALE_OFFSET) / DB_SCALE_OFFSET;
jamie@55 87 result[M + n] = n * nyquist;
jamie@54 88 }
jamie@54 89 break;
jamie@54 90 default:
jamie@54 91 /* MAGNITUDE_SPECTRUM */
jamie@54 92 for(n = 0; n < M; n++){
jamie@54 93 result[n] = sqrt(SQ(rfft[n]) + SQ(rfft[N - n])) / N;
jamie@55 94 result[M + n] = n * nyquist;
jamie@54 95 }
jamie@54 96 break;
jamie@1 97 }
jamie@1 98
jamie@54 99 /* result[0] = fabs(temp[0]) / N */
jamie@55 100 result[M] = nyquist * .5;
jamie@1 101
jamie@1 102 fftwf_destroy_plan(plan);
jamie@54 103 fftwf_free(rfft);
jamie@43 104 free(input);
jamie@1 105
jamie@38 106 return SUCCESS;
jamie@1 107 }
jamie@1 108
jamie@43 109 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@1 110
jamie@43 111 float *temp, *input;
jamie@43 112 size_t bytes;
jamie@1 113 int n;
jamie@1 114 fftwf_plan plan;
jamie@1 115
jamie@1 116 temp = (float *)fftwf_malloc(N * sizeof(float));
jamie@43 117 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 118 input = memcpy(input, data, bytes);
jamie@43 119
jamie@43 120 plan = fftwf_plan_r2r_1d(N, input, temp, FFTW_HC2R, FFTW_ESTIMATE);
jamie@1 121
jamie@1 122 fftwf_execute(plan);
jamie@1 123
jamie@1 124 for(n = 0; n < N - 1; n++)
jamie@1 125 result[n] = temp[n+1];
jamie@1 126
jamie@1 127 fftwf_destroy_plan(plan);
jamie@1 128 fftwf_free(temp);
jamie@43 129 free(input);
jamie@38 130
jamie@38 131 return SUCCESS;
jamie@1 132 }
jamie@1 133
jamie@43 134 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 135
jamie@30 136 xtract_mel_filter *f;
jamie@43 137 float *input;
jamie@43 138 size_t bytes;
jamie@30 139 int n, filter;
jamie@30 140
jamie@30 141 f = (xtract_mel_filter *)argv;
jamie@39 142
jamie@43 143 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 144 input = memcpy(input, data, bytes);
jamie@43 145
jamie@30 146 for(filter = 0; filter < f->n_filters; filter++){
jamie@30 147 for(n = 0; n < N; n++){
jamie@43 148 result[filter] += input[n] * f->filters[filter][n];
jamie@30 149 }
jamie@30 150 if(result[filter] < LOG_LIMIT) result[filter] = LOG_LIMIT;
jamie@30 151 result[filter] = log(result[filter]);
jamie@30 152 }
jamie@30 153
jamie@30 154 for(n = filter + 1; n < N; n++) result[n] = 0;
jamie@30 155
jamie@30 156 xtract_dct(result, f->n_filters, NULL, result);
jamie@30 157
jamie@43 158 free(input);
jamie@43 159
jamie@38 160 return SUCCESS;
jamie@30 161 }
jamie@30 162
jamie@43 163 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 164
jamie@30 165 fftwf_plan plan;
jamie@43 166 float *input;
jamie@43 167 size_t bytes;
jamie@30 168
jamie@43 169 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 170 input = memcpy(input, data, bytes);
jamie@43 171
jamie@30 172 plan =
jamie@43 173 fftwf_plan_r2r_1d(N, input, result, FFTW_REDFT00, FFTW_ESTIMATE);
jamie@30 174
jamie@30 175 fftwf_execute(plan);
jamie@30 176 fftwf_destroy_plan(plan);
jamie@43 177 free(input);
jamie@38 178
jamie@38 179 return SUCCESS;
jamie@30 180 }
jamie@30 181
jamie@30 182 #else
jamie@30 183
jamie@43 184 int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@30 185
jamie@34 186 NEEDS_FFTW;
jamie@30 187
jamie@30 188 }
jamie@30 189
jamie@43 190 int xtract_autocorrelation_fft(const float *data, const int N, const void *argv, float *result){
jamie@30 191
jamie@34 192 NEEDS_FFTW;
jamie@30 193
jamie@30 194 }
jamie@30 195
jamie@43 196 int xtract_mfcc(const float *data, const int N, const void *argv, float *result){
jamie@30 197
jamie@34 198 NEEDS_FFTW;
jamie@30 199
jamie@30 200 }
jamie@30 201
jamie@43 202 int xtract_dct(const float *data, const int N, const void *argv, float *result){
jamie@30 203
jamie@34 204 NEEDS_FFTW;
jamie@30 205
jamie@30 206 }
jamie@30 207
jamie@30 208 #endif
jamie@30 209
jamie@43 210 int xtract_autocorrelation(const float *data, const int N, const void *argv, float *result){
jamie@30 211
jamie@30 212 /* Naive time domain implementation */
jamie@30 213
jamie@30 214 int n = N, i;
jamie@30 215
jamie@30 216 float corr;
jamie@30 217
jamie@30 218 while(n--){
jamie@30 219 corr = 0;
jamie@30 220 for(i = 0; i < N - n; i++){
jamie@30 221 corr += data[i] * data[i + n];
jamie@30 222 }
jamie@30 223 result[n] = corr / N;
jamie@30 224 }
jamie@38 225
jamie@38 226 return SUCCESS;
jamie@30 227 }
jamie@30 228
jamie@43 229 int xtract_amdf(const float *data, const int N, const void *argv, float *result){
jamie@1 230
jamie@1 231 int n = N, i;
jamie@1 232
jamie@6 233 float md, temp;
jamie@1 234
jamie@1 235 while(n--){
jamie@1 236 md = 0;
jamie@1 237 for(i = 0; i < N - n; i++){
jamie@6 238 temp = data[i] - data[i + n];
jamie@6 239 temp = (temp < 0 ? -temp : temp);
jamie@6 240 md += temp;
jamie@1 241 }
jamie@1 242 result[n] = md / N;
jamie@1 243 }
jamie@38 244
jamie@38 245 return SUCCESS;
jamie@1 246 }
jamie@1 247
jamie@43 248 int xtract_asdf(const float *data, const int N, const void *argv, float *result){
jamie@1 249
jamie@1 250 int n = N, i;
jamie@1 251
jamie@1 252 float sd;
jamie@1 253
jamie@1 254 while(n--){
jamie@1 255 sd = 0;
jamie@1 256 for(i = 0; i < N - n; i++){
jamie@6 257 /*sd = 1;*/
jamie@1 258 sd += SQ(data[i] - data[i + n]);
jamie@1 259 }
jamie@1 260 result[n] = sd / N;
jamie@1 261 }
jamie@38 262
jamie@38 263 return SUCCESS;
jamie@1 264 }
jamie@1 265
jamie@43 266 int xtract_bark_coefficients(const float *data, const int N, const void *argv, float *result){
jamie@1 267
jamie@1 268 int *limits, band, n;
jamie@1 269
jamie@1 270 limits = (int *)argv;
jamie@1 271
jamie@1 272 for(band = 0; band < BARK_BANDS; band++){
jamie@1 273 for(n = limits[band]; n < limits[band + 1]; n++)
jamie@1 274 result[band] += data[n];
jamie@1 275 }
jamie@38 276
jamie@38 277 return SUCCESS;
jamie@1 278 }
jamie@1 279
jamie@52 280 int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@1 281
jamie@55 282 float threshold, max, y, y2, y3, p, nyquist, *input = NULL;
jamie@43 283 size_t bytes;
jamie@49 284 int n = N, M, rv = SUCCESS;
jamie@49 285
jamie@55 286 threshold = max = y = y2 = y3 = p = nyquist = 0.f;
jamie@1 287
jamie@1 288 if(argv != NULL){
jamie@55 289 nyquist = ((float *)argv)[0];
jamie@55 290 threshold = ((float *)argv)[1];
jamie@1 291 }
jamie@49 292 else
jamie@49 293 rv = BAD_ARGV;
jamie@49 294
jamie@55 295 if(threshold < 0 || threshold > 100){
jamie@55 296 threshold = 0;
jamie@49 297 rv = BAD_ARGV;
jamie@1 298 }
jamie@1 299
jamie@55 300 CHECK_nyquist;
jamie@49 301
jamie@43 302 input = (float *)malloc(bytes = N * sizeof(float));
jamie@43 303
jamie@43 304 if(input != NULL)
jamie@43 305 input = memcpy(input, data, bytes);
jamie@43 306 else
jamie@43 307 return MALLOC_FAILED;
jamie@43 308
jamie@1 309 M = N >> 1;
jamie@1 310
jamie@45 311 while(n--)
jamie@43 312 max = MAX(max, input[n]);
jamie@1 313
jamie@55 314 threshold *= .01 * max;
jamie@1 315
jamie@1 316 result[0] = 0;
jamie@1 317 result[M] = 0;
jamie@1 318
jamie@1 319 for(n = 1; n < M; n++){
jamie@55 320 if(input[n] >= threshold){
jamie@43 321 if(input[n] > input[n - 1] && input[n] > input[n + 1]){
jamie@55 322 result[M + n] = nyquist * (n + (p = .5 * (y = input[n-1] -
jamie@52 323 (y3 = input[n+1])) / (input[n - 1] - 2 *
jamie@52 324 (y2 = input[n]) + input[n + 1])));
jamie@52 325 result[n] = y2 - .25 * (y - y3) * p;
jamie@1 326 }
jamie@1 327 else{
jamie@1 328 result[n] = 0;
jamie@1 329 result[M + n] = 0;
jamie@1 330 }
jamie@1 331 }
jamie@1 332 else{
jamie@1 333 result[n] = 0;
jamie@1 334 result[M + n] = 0;
jamie@1 335 }
jamie@1 336 }
jamie@1 337
jamie@43 338 free(input);
jamie@49 339 return (rv ? rv : SUCCESS);
jamie@1 340 }
jamie@41 341
jamie@52 342 int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){
jamie@38 343
jamie@38 344 int n = (N >> 1), M = n;
jamie@38 345
jamie@43 346 const float *freqs, *amps;
jamie@55 347 float f0, threshold, ratio, nearest, distance;
jamie@38 348
jamie@52 349 amps = data;
jamie@52 350 freqs = data + n;
jamie@38 351 f0 = *((float *)argv);
jamie@55 352 threshold = *((float *)argv+1);
jamie@38 353
jamie@38 354 ratio = nearest = distance = 0.f;
jamie@38 355
jamie@38 356 while(n--){
jamie@38 357 if(freqs[n]){
jamie@38 358 ratio = freqs[n] / f0;
jamie@38 359 nearest = round(ratio);
jamie@38 360 distance = fabs(nearest - ratio);
jamie@55 361 if(distance > threshold)
jamie@38 362 result[n] = result[M + n] = 0.f;
jamie@42 363 else {
jamie@52 364 result[n] = amps[n];
jamie@52 365 result[M + n] = freqs[n];
jamie@42 366 }
jamie@38 367 }
jamie@38 368 else
jamie@38 369 result[n] = result[M + n] = 0.f;
jamie@38 370 }
jamie@38 371 return SUCCESS;
jamie@38 372 }
jamie@38 373