/* fft.c */ #include #include #include #include #include "mem.h" #include "fft.h" #define FFT_SIGN (-1) int fft_size = 0; fft_type *fft_buffer = NULL; long fft_logN; void fft_init(int size) { assert(fft_size == 0); assert(fft_buffer == NULL); /* We use complex pairs, so we need twice the number of elements */ fft_buffer = safe_malloc(sizeof(fft_type) * size * 2); fft_size = size; fft_logN = (long)(log(fft_size)/log(2.0)+0.5); } void fft_data_float(float *buf) { int i; for (i = 0; i < fft_size; i++) { fft_buffer[i*2] = buf[i]; fft_buffer[i*2+1] = 0.0; } } void fft_data_signed16(int16_t *buf) { int i; for (i = 0; i < fft_size; i++) { fft_buffer[i*2] = (fft_type)buf[i] / (INT16_MAX+1); fft_buffer[i*2+1] = 0.0; // printf("input: %f, %f\n", fft_buffer[i*2], fft_buffer[i*2+1]); } } void fft_data_unsigned16(uint16_t *buf) { int i; for (i = 0; i < fft_size; i++) { fft_buffer[i*2] = (fft_type)buf[i] / (INT16_MAX+1) - (INT16_MAX+1); fft_buffer[i*2+1] = 0.0; } } fft_type *fft_getresult(void) { return fft_buffer; } void fft_window(void) { int i; for (i = 0; i < fft_size; i++) { fft_buffer[2*i] = fft_buffer[2*i] * (0.5 + 0.5 * cos(M_PI * (i - fft_size/2)/(fft_size/2 + 1))); } } /* * FFT routine * Based on routine (C) 1996 S.M.Bernsee. */ void fft_compute(void) { fft_type wr, wi, arg, *p1, *p2, temp; fft_type tr, ti, ur, ui, *p1r, *p1i, *p2r, *p2i; long i, bitm, j, le, le2, k; for (i = 2; i < 2*fft_size-2; i += 2) { for (bitm = 2, j = 0; bitm < 2*fft_size; bitm <<= 1) { if (i & bitm) j++; j <<= 1; } if (i < j) { p1 = fft_buffer+i; p2 = fft_buffer+j; temp = *p1; *(p1++) = *p2; *(p2++) = temp; temp = *p1; *p1 = *p2; *p2 = temp; } } for (k = 0, le = 2; k < fft_logN; k++) { le <<= 1; le2 = le>>1; ur = 1.0; ui = 0.0; arg = M_PI / (le2>>1); wr = cos(arg); wi = FFT_SIGN*sin(arg); for (j = 0; j < le2; j += 2) { p1r = fft_buffer+j; p1i = p1r+1; p2r = p1r+le2; p2i = p2r+1; for (i = j; i < 2*fft_size; i += le) { tr = *p2r * ur - *p2i * ui; ti = *p2r * ui + *p2i * ur; *p2r = *p1r - tr; *p2i = *p1i - ti; *p1r += tr; *p1i += ti; p1r += le; p1i += le; p2r += le; p2i += le; } tr = ur*wr - ui*wi; ui = ur*wi + ui*wr; ur = tr; } } }