annotate src/vector.c @ 52:45c585bb7996

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