annotate src/vector.c @ 56:450712b21565

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