annotate src/vector.c @ 38:0ea4d6430cfc

Implemented xtract_harmonics
author Jamie Bullock <jamie@postlude.co.uk>
date Sat, 09 Dec 2006 15:21:35 +0000
parents 29e2738a376d
children 39c76f4db5b7
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@30 26
jamie@30 27 #ifdef XTRACT_FFT
jamie@30 28
jamie@1 29 #include <fftw3.h>
jamie@1 30
jamie@1 31 int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
jamie@1 32
jamie@1 33 float *temp;
jamie@1 34 int n , M = N >> 1;
jamie@1 35 fftwf_plan plan;
jamie@1 36
jamie@1 37 temp = (float *)fftwf_malloc(N * sizeof(float));
jamie@1 38
jamie@1 39 plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_R2HC, FFTW_ESTIMATE);
jamie@1 40
jamie@1 41 fftwf_execute(plan);
jamie@1 42
jamie@1 43 for(n = 1; n < M; n++){
jamie@1 44 result[n] = sqrt(SQ(temp[n]) + SQ(temp[N - n])) / N;
jamie@1 45 result[N-n] = 0.0f;
jamie@1 46 }
jamie@1 47
jamie@1 48 result[0] = fabs(temp[0]) / N;
jamie@1 49 result[M] = fabs(temp[M]) / N;
jamie@1 50
jamie@1 51 fftwf_destroy_plan(plan);
jamie@1 52 fftwf_free(temp);
jamie@1 53
jamie@38 54 return SUCCESS;
jamie@1 55 }
jamie@1 56
jamie@1 57 int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
jamie@1 58
jamie@1 59 float *temp;
jamie@1 60 int n;
jamie@1 61 fftwf_plan plan;
jamie@1 62
jamie@1 63 temp = (float *)fftwf_malloc(N * sizeof(float));
jamie@1 64 plan = fftwf_plan_r2r_1d(N, data, temp, FFTW_HC2R, FFTW_ESTIMATE);
jamie@1 65
jamie@1 66 fftwf_execute(plan);
jamie@1 67
jamie@1 68 for(n = 0; n < N - 1; n++)
jamie@1 69 result[n] = temp[n+1];
jamie@1 70
jamie@1 71 fftwf_destroy_plan(plan);
jamie@1 72 fftwf_free(temp);
jamie@38 73
jamie@38 74 return SUCCESS;
jamie@1 75 }
jamie@1 76
jamie@30 77 int xtract_mfcc(float *data, int N, void *argv, float *result){
jamie@30 78
jamie@30 79 xtract_mel_filter *f;
jamie@30 80 int n, filter;
jamie@30 81
jamie@30 82 f = (xtract_mel_filter *)argv;
jamie@30 83
jamie@30 84 for(filter = 0; filter < f->n_filters; filter++){
jamie@30 85 for(n = 0; n < N; n++){
jamie@30 86 result[filter] += data[n] * f->filters[filter][n];
jamie@30 87 }
jamie@30 88 if(result[filter] < LOG_LIMIT) result[filter] = LOG_LIMIT;
jamie@30 89 result[filter] = log(result[filter]);
jamie@30 90 }
jamie@30 91
jamie@30 92 for(n = filter + 1; n < N; n++) result[n] = 0;
jamie@30 93
jamie@30 94 xtract_dct(result, f->n_filters, NULL, result);
jamie@30 95
jamie@38 96 return SUCCESS;
jamie@30 97 }
jamie@30 98
jamie@30 99 int xtract_dct(float *data, int N, void *argv, float *result){
jamie@30 100
jamie@30 101 fftwf_plan plan;
jamie@30 102
jamie@30 103 plan =
jamie@30 104 fftwf_plan_r2r_1d(N, data, result, FFTW_REDFT00, FFTW_ESTIMATE);
jamie@30 105
jamie@30 106 fftwf_execute(plan);
jamie@30 107 fftwf_destroy_plan(plan);
jamie@38 108
jamie@38 109 return SUCCESS;
jamie@30 110 }
jamie@30 111
jamie@30 112 #else
jamie@30 113
jamie@30 114 int xtract_magnitude_spectrum(float *data, int N, void *argv, float *result){
jamie@30 115
jamie@34 116 NEEDS_FFTW;
jamie@30 117
jamie@30 118 }
jamie@30 119
jamie@30 120 int xtract_autocorrelation_fft(float *data, int N, void *argv, float *result){
jamie@30 121
jamie@34 122 NEEDS_FFTW;
jamie@30 123
jamie@30 124 }
jamie@30 125
jamie@30 126 int xtract_mfcc(float *data, int N, void *argv, float *result){
jamie@30 127
jamie@34 128 NEEDS_FFTW;
jamie@30 129
jamie@30 130 }
jamie@30 131
jamie@30 132 int xtract_dct(float *data, int N, void *argv, float *result){
jamie@30 133
jamie@34 134 NEEDS_FFTW;
jamie@30 135
jamie@30 136 }
jamie@30 137
jamie@30 138 #endif
jamie@30 139
jamie@30 140 int xtract_autocorrelation(float *data, int N, void *argv, float *result){
jamie@30 141
jamie@30 142 /* Naive time domain implementation */
jamie@30 143
jamie@30 144 int n = N, i;
jamie@30 145
jamie@30 146 float corr;
jamie@30 147
jamie@30 148 while(n--){
jamie@30 149 corr = 0;
jamie@30 150 for(i = 0; i < N - n; i++){
jamie@30 151 corr += data[i] * data[i + n];
jamie@30 152 }
jamie@30 153 result[n] = corr / N;
jamie@30 154 }
jamie@38 155
jamie@38 156 return SUCCESS;
jamie@30 157 }
jamie@30 158
jamie@1 159 int xtract_amdf(float *data, int N, void *argv, float *result){
jamie@1 160
jamie@1 161 int n = N, i;
jamie@1 162
jamie@6 163 float md, temp;
jamie@1 164
jamie@1 165 while(n--){
jamie@1 166 md = 0;
jamie@1 167 for(i = 0; i < N - n; i++){
jamie@6 168 temp = data[i] - data[i + n];
jamie@6 169 temp = (temp < 0 ? -temp : temp);
jamie@6 170 md += temp;
jamie@1 171 }
jamie@1 172 result[n] = md / N;
jamie@1 173 }
jamie@38 174
jamie@38 175 return SUCCESS;
jamie@1 176 }
jamie@1 177
jamie@1 178 int xtract_asdf(float *data, int N, void *argv, float *result){
jamie@1 179
jamie@1 180 int n = N, i;
jamie@1 181
jamie@1 182 float sd;
jamie@1 183
jamie@1 184 while(n--){
jamie@1 185 sd = 0;
jamie@1 186 for(i = 0; i < N - n; i++){
jamie@6 187 /*sd = 1;*/
jamie@1 188 sd += SQ(data[i] - data[i + n]);
jamie@1 189 }
jamie@1 190 result[n] = sd / N;
jamie@1 191 }
jamie@38 192
jamie@38 193 return SUCCESS;
jamie@1 194 }
jamie@1 195
jamie@1 196 int xtract_bark_coefficients(float *data, int N, void *argv, float *result){
jamie@1 197
jamie@1 198 int *limits, band, n;
jamie@1 199
jamie@1 200 limits = (int *)argv;
jamie@1 201
jamie@1 202 for(band = 0; band < BARK_BANDS; band++){
jamie@1 203 for(n = limits[band]; n < limits[band + 1]; n++)
jamie@1 204 result[band] += data[n];
jamie@1 205 }
jamie@38 206
jamie@38 207 return SUCCESS;
jamie@1 208 }
jamie@1 209
jamie@1 210 int xtract_peaks(float *data, int N, void *argv, float *result){
jamie@1 211
jamie@1 212 float thresh, max, y, y2, y3, p, width, sr;
jamie@38 213 int n = N, M, return_code = SUCCESS;
jamie@1 214
jamie@1 215 if(argv != NULL){
jamie@1 216 thresh = ((float *)argv)[0];
jamie@1 217 sr = ((float *)argv)[1];
jamie@1 218 return_code = BAD_ARGV;
jamie@1 219 }
jamie@1 220 else{
jamie@1 221 thresh = 0;
jamie@1 222 sr = 44100;
jamie@1 223 }
jamie@1 224
jamie@1 225 M = N >> 1;
jamie@1 226 width = sr / N;
jamie@1 227
jamie@1 228 y = y2 = y3 = p = max = 0;
jamie@1 229
jamie@1 230 if(thresh < 0 || thresh > 100){
jamie@1 231 thresh = 0;
jamie@1 232 return_code = BAD_ARGV;
jamie@1 233 }
jamie@1 234
jamie@1 235 if(!sr){
jamie@1 236 sr = 44100;
jamie@1 237 return_code = BAD_ARGV;
jamie@1 238 }
jamie@1 239
jamie@1 240 while(n--){
jamie@1 241 max = MAX(max, data[n]);
jamie@1 242 /* ensure we never take log10(0) */
jamie@1 243 /*data[n] = (data[n] < LOG_LIMIT ? LOG_LIMIT : data[n]);*/
jamie@1 244 if ((data[n] * 100000) <= 1)
jamie@1 245 /* We get a more stable peak this way */
jamie@1 246 data[n] = 1;
jamie@1 247
jamie@1 248 }
jamie@1 249
jamie@1 250 thresh *= .01 * max;
jamie@1 251
jamie@1 252 result[0] = 0;
jamie@1 253 result[M] = 0;
jamie@1 254
jamie@1 255 for(n = 1; n < M; n++){
jamie@1 256 if(data[n] >= thresh){
jamie@1 257 if(data[n] > data[n - 1] && data[n] > data[n + 1]){
jamie@1 258 result[n] = width * (n + (p = .5 * (y = 20 * log10(data[n-1]) - (y3 = 20 * log10(data[n+1]))) / (20 * log10(data[n - 1]) - 2 * (y2 = 20 * log10(data[n])) + 20 * log10(data[n + 1]))));
jamie@1 259 result[M + n] = y2 - .25 * (y - y3) * p;
jamie@1 260 }
jamie@1 261 else{
jamie@1 262 result[n] = 0;
jamie@1 263 result[M + n] = 0;
jamie@1 264 }
jamie@1 265 }
jamie@1 266 else{
jamie@1 267 result[n] = 0;
jamie@1 268 result[M + n] = 0;
jamie@1 269 }
jamie@1 270 }
jamie@1 271
jamie@1 272 return (return_code ? return_code : SUCCESS);
jamie@1 273 }
jamie@1 274
jamie@38 275 int xtract_harmonics(float *data, int N, void *argv, float *result){
jamie@38 276
jamie@38 277 int n = (N >> 1), M = n;
jamie@38 278
jamie@38 279 float *freqs, *amps, f0, thresh, ratio, nearest, distance;
jamie@38 280
jamie@38 281 freqs = data;
jamie@38 282 amps = data + n;
jamie@38 283 f0 = *((float *)argv);
jamie@38 284 thresh = *((float *)argv+1);
jamie@38 285
jamie@38 286 ratio = nearest = distance = 0.f;
jamie@38 287
jamie@38 288 while(n--){
jamie@38 289 if(freqs[n]){
jamie@38 290 ratio = freqs[n] / f0;
jamie@38 291 nearest = round(ratio);
jamie@38 292 distance = fabs(nearest - ratio);
jamie@38 293 if(distance > thresh)
jamie@38 294 result[n] = result[M + n] = 0.f;
jamie@38 295 else
jamie@38 296 result[n] = result[M + n] = freqs[n];
jamie@38 297 }
jamie@38 298 else
jamie@38 299 result[n] = result[M + n] = 0.f;
jamie@38 300 }
jamie@38 301 return SUCCESS;
jamie@38 302 }
jamie@38 303