annotate src/vector.c @ 68:9de5628b69a8

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