Mercurial > hg > libxtract
comparison 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 |
comparison
equal
deleted
inserted
replaced
51:5306739416cf | 52:45c585bb7996 |
---|---|
30 | 30 |
31 #include <fftw3.h> | 31 #include <fftw3.h> |
32 | 32 |
33 int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result){ | 33 int xtract_magnitude_spectrum(const float *data, const int N, const void *argv, float *result){ |
34 | 34 |
35 float *temp, *input, q, sr; | 35 float *temp, *input, q; |
36 size_t bytes; | 36 size_t bytes; |
37 int n , M = N >> 1; | 37 int n , M = N >> 1; |
38 fftwf_plan plan; | 38 fftwf_plan plan; |
39 | 39 |
40 temp = (float *)fftwf_malloc(N * sizeof(float)); | 40 temp = (float *)fftwf_malloc(N * sizeof(float)); |
41 input = (float *)malloc(bytes = N * sizeof(float)); | 41 input = (float *)malloc(bytes = N * sizeof(float)); |
42 input = memcpy(input, data, bytes); | 42 input = memcpy(input, data, bytes); |
43 | 43 |
44 q = sr = 0.f; | 44 q = *(float *)argv; |
45 | 45 |
46 sr = *(float *)argv; | 46 CHECK_q; |
47 | |
48 CHECK_SR; | |
49 | |
50 q = (sr * .5) / M; | |
51 | 47 |
52 plan = fftwf_plan_r2r_1d(N, input, temp, FFTW_R2HC, FFTW_ESTIMATE); | 48 plan = fftwf_plan_r2r_1d(N, input, temp, FFTW_R2HC, FFTW_ESTIMATE); |
53 | 49 |
54 fftwf_execute(plan); | 50 fftwf_execute(plan); |
55 | 51 |
56 for(n = 1; n < M; n++){ | 52 for(n = 1; n < M; n++){ |
57 result[M + n] = sqrt(SQ(temp[n]) + SQ(temp[N - n])) / N; | 53 result[n] = sqrt(SQ(temp[n]) + SQ(temp[N - n])) / N; |
58 result[n] = n * q; | 54 result[M + n] = n * q; |
59 } | 55 } |
60 | 56 |
61 result[M] = fabs(temp[0]) / N; | 57 result[0] = fabs(temp[0]) / N; |
62 result[0] = q * .5; | 58 result[M] = q * .5; |
63 | 59 |
64 fftwf_destroy_plan(plan); | 60 fftwf_destroy_plan(plan); |
65 fftwf_free(temp); | 61 fftwf_free(temp); |
66 free(input); | 62 free(input); |
67 | 63 |
237 } | 233 } |
238 | 234 |
239 return SUCCESS; | 235 return SUCCESS; |
240 } | 236 } |
241 | 237 |
242 int xtract_peaks(const float *data, const int N, const void *argv, float *result){ | 238 int xtract_peak_spectrum(const float *data, const int N, const void *argv, float *result){ |
243 | 239 |
244 float thresh, max, y, y2, | 240 float thresh, max, y, y2, y3, p, q, *input = NULL; |
245 y3, p, width, sr, | |
246 *input = NULL; | |
247 size_t bytes; | 241 size_t bytes; |
248 int n = N, M, rv = SUCCESS; | 242 int n = N, M, rv = SUCCESS; |
249 | 243 |
250 thresh = max = y = y2 = y3 = p = width = sr = 0.f; | 244 thresh = max = y = y2 = y3 = p = q = 0.f; |
251 | 245 |
252 if(argv != NULL){ | 246 if(argv != NULL){ |
253 thresh = ((float *)argv)[0]; | 247 thresh = ((float *)argv)[0]; |
254 sr = ((float *)argv)[1]; | 248 q = ((float *)argv)[1]; |
255 } | 249 } |
256 else | 250 else |
257 rv = BAD_ARGV; | 251 rv = BAD_ARGV; |
258 | 252 |
259 if(thresh < 0 || thresh > 100){ | 253 if(thresh < 0 || thresh > 100){ |
260 thresh = 0; | 254 thresh = 0; |
261 rv = BAD_ARGV; | 255 rv = BAD_ARGV; |
262 } | 256 } |
263 | 257 |
264 CHECK_SR; | 258 CHECK_q; |
265 | 259 |
266 input = (float *)malloc(bytes = N * sizeof(float)); | 260 input = (float *)malloc(bytes = N * sizeof(float)); |
267 | 261 |
268 if(input != NULL) | 262 if(input != NULL) |
269 input = memcpy(input, data, bytes); | 263 input = memcpy(input, data, bytes); |
270 else | 264 else |
271 return MALLOC_FAILED; | 265 return MALLOC_FAILED; |
272 | 266 |
273 M = N >> 1; | 267 M = N >> 1; |
274 width = sr / N; | |
275 | 268 |
276 while(n--) | 269 while(n--) |
277 max = MAX(max, input[n]); | 270 max = MAX(max, input[n]); |
278 | 271 |
279 thresh *= .01 * max; | 272 thresh *= .01 * max; |
282 result[M] = 0; | 275 result[M] = 0; |
283 | 276 |
284 for(n = 1; n < M; n++){ | 277 for(n = 1; n < M; n++){ |
285 if(input[n] >= thresh){ | 278 if(input[n] >= thresh){ |
286 if(input[n] > input[n - 1] && input[n] > input[n + 1]){ | 279 if(input[n] > input[n - 1] && input[n] > input[n + 1]){ |
287 result[n] = width * (n + (p = .5 * (y = input[n-1] - (y3 = input[n+1])) / (input[n - 1] - 2 * (y2 = input[n]) + input[n + 1]))); | 280 result[M + n] = q * (n + (p = .5 * (y = input[n-1] - |
288 result[M + n] = y2 - .25 * (y - y3) * p; | 281 (y3 = input[n+1])) / (input[n - 1] - 2 * |
282 (y2 = input[n]) + input[n + 1]))); | |
283 result[n] = y2 - .25 * (y - y3) * p; | |
289 } | 284 } |
290 else{ | 285 else{ |
291 result[n] = 0; | 286 result[n] = 0; |
292 result[M + n] = 0; | 287 result[M + n] = 0; |
293 } | 288 } |
300 | 295 |
301 free(input); | 296 free(input); |
302 return (rv ? rv : SUCCESS); | 297 return (rv ? rv : SUCCESS); |
303 } | 298 } |
304 | 299 |
305 int xtract_harmonics(const float *data, const int N, const void *argv, float *result){ | 300 int xtract_harmonic_spectrum(const float *data, const int N, const void *argv, float *result){ |
306 | 301 |
307 int n = (N >> 1), M = n; | 302 int n = (N >> 1), M = n; |
308 | 303 |
309 const float *freqs, *amps; | 304 const float *freqs, *amps; |
310 float f0, thresh, ratio, nearest, distance; | 305 float f0, thresh, ratio, nearest, distance; |
311 | 306 |
312 freqs = data; | 307 amps = data; |
313 amps = data + n; | 308 freqs = data + n; |
314 f0 = *((float *)argv); | 309 f0 = *((float *)argv); |
315 thresh = *((float *)argv+1); | 310 thresh = *((float *)argv+1); |
316 | 311 |
317 ratio = nearest = distance = 0.f; | 312 ratio = nearest = distance = 0.f; |
318 | 313 |
322 nearest = round(ratio); | 317 nearest = round(ratio); |
323 distance = fabs(nearest - ratio); | 318 distance = fabs(nearest - ratio); |
324 if(distance > thresh) | 319 if(distance > thresh) |
325 result[n] = result[M + n] = 0.f; | 320 result[n] = result[M + n] = 0.f; |
326 else { | 321 else { |
327 result[n] = freqs[n]; | 322 result[n] = amps[n]; |
328 result[M + n] = amps[n]; | 323 result[M + n] = freqs[n]; |
329 } | 324 } |
330 } | 325 } |
331 else | 326 else |
332 result[n] = result[M + n] = 0.f; | 327 result[n] = result[M + n] = 0.f; |
333 } | 328 } |