123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <math.h>
- #include <complex.h>
- #include "fft.h"
- #define TWO_PI 6.28318530
- #define USE_SPLIT_RADIX 1
- #define LARGE_BASE_CASE 1
- fft_config_t *fft_init(int size, fft_type_t type, fft_direction_t direction, float *input, float *output)
- {
-
- int k,m;
- fft_config_t *config = (fft_config_t *)malloc(sizeof(fft_config_t));
-
- if ((size & (size-1)) != 0)
- return NULL;
-
- config->flags = 0;
- config->type = type;
- config->direction = direction;
- config->size = size;
-
- config->twiddle_factors = (float *)malloc(2 * config->size * sizeof(float));
- float two_pi_by_n = TWO_PI / config->size;
- for (k = 0, m = 0 ; k < config->size ; k++, m+=2)
- {
- config->twiddle_factors[m] = cosf(two_pi_by_n * k);
- config->twiddle_factors[m+1] = sinf(two_pi_by_n * k);
- }
-
- if (input != NULL)
- config->input = input;
- else
- {
- if (config->type == FFT_REAL)
- config->input = (float *)malloc(config->size * sizeof(float));
- else if (config->type == FFT_COMPLEX)
- config->input = (float *)malloc(2 * config->size * sizeof(float));
- config->flags |= FFT_OWN_INPUT_MEM;
- }
- if (config->input == NULL)
- return NULL;
-
- if (output != NULL)
- config->output = output;
- else
- {
- if (config->type == FFT_REAL)
- config->output = (float *)malloc(config->size * sizeof(float));
- else if (config->type == FFT_COMPLEX)
- config->output = (float *)malloc(2 * config->size * sizeof(float));
- config->flags |= FFT_OWN_OUTPUT_MEM;
- }
- if (config->output == NULL)
- return NULL;
- return config;
- }
- void fft_destroy(fft_config_t *config)
- {
- if (config->flags & FFT_OWN_INPUT_MEM)
- free(config->input);
- if (config->flags & FFT_OWN_OUTPUT_MEM)
- free(config->output);
- free(config->twiddle_factors);
- free(config);
- }
- void fft_execute(fft_config_t *config)
- {
- if (config->type == FFT_REAL && config->direction == FFT_FORWARD)
- rfft(config->input, config->output, config->twiddle_factors, config->size);
- else if (config->type == FFT_REAL && config->direction == FFT_BACKWARD)
- irfft(config->input, config->output, config->twiddle_factors, config->size);
- else if (config->type == FFT_COMPLEX && config->direction == FFT_FORWARD)
- fft(config->input, config->output, config->twiddle_factors, config->size);
- else if (config->type == FFT_COMPLEX && config->direction == FFT_BACKWARD)
- ifft(config->input, config->output, config->twiddle_factors, config->size);
- }
- void fft(float *input, float *output, float *twiddle_factors, int n)
- {
-
- #if USE_SPLIT_RADIX
- split_radix_fft(input, output, n, 2, twiddle_factors, 2);
- #else
- fft_primitive(input, output, n, 2, twiddle_factors, 2);
- #endif
- }
- void ifft(float *input, float *output, float *twiddle_factors, int n)
- {
-
- ifft_primitive(input, output, n, 2, twiddle_factors, 2);
- }
- void rfft(float *x, float *y, float *twiddle_factors, int n)
- {
-
- #if USE_SPLIT_RADIX
- split_radix_fft(x, y, n / 2, 2, twiddle_factors, 4);
- #else
- fft_primitive(x, y, n / 2, 2, twiddle_factors, 4);
- #endif
-
-
- float t = y[0];
- y[0] = t + y[1];
- y[1] = t - y[1];
-
-
- y[n/2+1] = -y[n/2+1];
-
- int k;
- for (k = 2 ; k < n / 2 ; k += 2)
- {
- float xer, xei, xor_t, xoi, c, s, tr, ti;
- c = twiddle_factors[k];
- s = twiddle_factors[k+1];
-
-
- xer = 0.5 * (y[k] + y[n-k]);
- xei = 0.5 * (y[k+1] - y[n-k+1]);
-
- xor_t = 0.5 * (y[k+1] + y[n-k+1]);
- xoi = - 0.5 * (y[k] - y[n-k]);
- tr = c * xor_t + s * xoi;
- ti = -s * xor_t + c * xoi;
- y[k] = xer + tr;
- y[k+1] = xei + ti;
- y[n-k] = xer - tr;
- y[n-k+1] = -(xei - ti);
- }
- }
- void irfft(float *x, float *y, float *twiddle_factors, int n)
- {
-
- int k;
-
- float t = x[0];
- x[0] = 0.5 * (t + x[1]);
- x[1] = 0.5 * (t - x[1]);
- x[n/2+1] = -x[n/2+1];
- for (k = 2 ; k < n / 2 ; k += 2)
- {
- float xer, xei, xor_t, xoi, c, s, tr, ti;
- c = twiddle_factors[k];
- s = twiddle_factors[k+1];
- xer = 0.5 * (x[k] + x[n-k]);
- tr = 0.5 * (x[k] - x[n-k]);
- xei = 0.5 * (x[k+1] - x[n-k+1]);
- ti = 0.5 * (x[k+1] + x[n-k+1]);
- xor_t = c * tr - s * ti;
- xoi = s * tr + c * ti;
- x[k] = xer - xoi;
- x[k+1] = xor_t + xei;
- x[n-k] = xer + xoi;
- x[n-k+1] = xor_t - xei;
- }
- ifft_primitive(x, y, n / 2, 2, twiddle_factors, 4);
- }
- void fft_primitive(float *x, float *y, int n, int stride, float *twiddle_factors, int tw_stride)
- {
-
- int k;
- float t;
- #if LARGE_BASE_CASE
-
- if (n == 8)
- {
- fft8(x, stride, y, 2);
- return;
- }
- #else
-
- if (n == 2)
- {
- y[0] = x[0] + x[stride];
- y[1] = x[1] + x[stride + 1];
- y[2] = x[0] - x[stride];
- y[3] = x[1] - x[stride + 1];
- return;
- }
- #endif
-
- fft_primitive(x, y, n / 2, 2 * stride, twiddle_factors, 2 * tw_stride);
- fft_primitive(x + stride, y+n, n / 2, 2 * stride, twiddle_factors, 2 * tw_stride);
-
-
- t = y[0];
- y[0] = t + y[n];
- y[n] = t - y[n];
- t = y[1];
- y[1] = t + y[n+1];
- y[n+1] = t - y[n+1];
- for (k = 1 ; k < n / 2 ; k++)
- {
- float x1r, x1i, x2r, x2i, c, s;
- c = twiddle_factors[k * tw_stride];
- s = twiddle_factors[k * tw_stride + 1];
- x1r = y[2 * k];
- x1i = y[2 * k + 1];
- x2r = c * y[n + 2 * k] + s * y[n + 2 * k + 1];
- x2i = -s * y[n + 2 * k] + c * y[n + 2 * k + 1];
- y[2 * k] = x1r + x2r;
- y[2 * k + 1] = x1i + x2i;
- y[n + 2 * k] = x1r - x2r;
- y[n + 2 * k + 1] = x1i - x2i;
- }
- }
- void split_radix_fft(float *x, float *y, int n, int stride, float *twiddle_factors, int tw_stride)
- {
-
- int k;
- #if LARGE_BASE_CASE
-
- if (n == 8)
- {
- fft8(x, stride, y, 2);
- return;
- }
- else if (n == 4)
- {
- fft4(x, stride, y, 2);
- return;
- }
- #else
-
- if (n == 2)
- {
- y[0] = x[0] + x[stride];
- y[1] = x[1] + x[stride + 1];
- y[2] = x[0] - x[stride];
- y[3] = x[1] - x[stride + 1];
- return;
- }
- else if (n == 1)
- {
- y[0] = x[0];
- y[1] = x[1];
- return;
- }
- #endif
-
- split_radix_fft(x, y, n / 2, 2 * stride, twiddle_factors, 2 * tw_stride);
- split_radix_fft(x + stride, y + n, n / 4, 4 * stride, twiddle_factors, 4 * tw_stride);
- split_radix_fft(x + 3 * stride, y + n + n / 2, n / 4, 4 * stride, twiddle_factors, 4 * tw_stride);
-
- float u1r, u1i, u2r, u2i, x1r, x1i, x2r, x2i;
- float t;
-
- u1r = y[0];
- u1i = y[1];
- u2r = y[n / 2];
- u2i = y[n / 2 + 1];
- x1r = y[n];
- x1i = y[n + 1];
- x2r = y[n / 2 + n];
- x2i = y[n / 2 + n + 1];
- t = x1r + x2r;
- y[0] = u1r + t;
- y[n] = u1r - t;
- t = x1i + x2i;
- y[1] = u1i + t;
- y[n + 1] = u1i - t;
- t = x2i - x1i;
- y[n / 2] = u2r - t;
- y[n + n / 2] = u2r + t;
- t = x1r - x2r;
- y[n / 2 + 1] = u2i - t;
- y[n + n / 2 + 1] = u2i + t;
- for (k = 1 ; k < n / 4 ; k++)
- {
- float u1r, u1i, u2r, u2i, x1r, x1i, x2r, x2i, c1, s1, c2, s2;
- c1 = twiddle_factors[k * tw_stride];
- s1 = twiddle_factors[k * tw_stride + 1];
- c2 = twiddle_factors[3 * k * tw_stride];
- s2 = twiddle_factors[3 * k * tw_stride + 1];
- u1r = y[2 * k];
- u1i = y[2 * k + 1];
- u2r = y[2 * k + n / 2];
- u2i = y[2 * k + n / 2 + 1];
- x1r = c1 * y[n + 2 * k] + s1 * y[n + 2 * k + 1];
- x1i = -s1 * y[n + 2 * k] + c1 * y[n + 2 * k + 1];
- x2r = c2 * y[n / 2 + n + 2 * k] + s2 * y[n / 2 + n + 2 * k + 1];
- x2i = -s2 * y[n / 2 + n + 2 * k] + c2 * y[n / 2 + n + 2 * k + 1];
- t = x1r + x2r;
- y[2 * k] = u1r + t;
- y[2 * k + n] = u1r - t;
- t = x1i + x2i;
- y[2 * k + 1] = u1i + t;
- y[2 * k + n + 1] = u1i - t;
- t = x2i - x1i;
- y[2 * k + n / 2] = u2r - t;
- y[2 * k + n + n / 2] = u2r + t;
- t = x1r - x2r;
- y[2 * k + n / 2 + 1] = u2i - t;
- y[2 * k + n + n / 2 + 1] = u2i + t;
- }
- }
- void ifft_primitive(float *input, float *output, int n, int stride, float *twiddle_factors, int tw_stride)
- {
- #if USE_SPLIT_RADIX
- split_radix_fft(input, output, n, stride, twiddle_factors, tw_stride);
- #else
- fft_primitive(input, output, n, stride, twiddle_factors, tw_stride);
- #endif
- int ks;
- int ns = n * stride;
-
- for (ks = stride ; ks < ns / 2 ; ks += stride)
- {
- float t;
- t = output[ks];
- output[ks] = output[ns-ks];
- output[ns-ks] = t;
- t = output[ks+1];
- output[ks+1] = output[ns-ks+1];
- output[ns-ks+1] = t;
- }
-
- float norm = 1. / n;
- for (ks = 0 ; ks < ns ; ks += stride)
- {
- output[ks] *= norm;
- output[ks+1] *= norm;
- }
- }
- inline void fft8(float *input, int stride_in, float *output, int stride_out)
- {
-
- float a0r, a1r, a2r, a3r, a4r, a5r, a6r, a7r;
- float a0i, a1i, a2i, a3i, a4i, a5i, a6i, a7i;
- float b0r, b1r, b2r, b3r, b4r, b5r, b6r, b7r;
- float b0i, b1i, b2i, b3i, b4i, b5i, b6i, b7i;
- float t;
- float sin_pi_4 = 0.7071067812;
- a0r = input[0];
- a0i = input[1];
- a1r = input[stride_in];
- a1i = input[stride_in+1];
- a2r = input[2*stride_in];
- a2i = input[2*stride_in+1];
- a3r = input[3*stride_in];
- a3i = input[3*stride_in+1];
- a4r = input[4*stride_in];
- a4i = input[4*stride_in+1];
- a5r = input[5*stride_in];
- a5i = input[5*stride_in+1];
- a6r = input[6*stride_in];
- a6i = input[6*stride_in+1];
- a7r = input[7*stride_in];
- a7i = input[7*stride_in+1];
-
- b0r = a0r + a4r;
- b0i = a0i + a4i;
- b1r = a1r + a5r;
- b1i = a1i + a5i;
- b2r = a2r + a6r;
- b2i = a2i + a6i;
- b3r = a3r + a7r;
- b3i = a3i + a7i;
- b4r = a0r - a4r;
- b4i = a0i - a4i;
- b5r = a1r - a5r;
- b5i = a1i - a5i;
-
- t = b5r + b5i;
- b5i = (b5i - b5r) * sin_pi_4;
- b5r = t * sin_pi_4;
-
- b6r = a2i - a6i;
- b6i = a6r - a2r;
- b7r = a3r - a7r;
- b7i = a3i - a7i;
-
- t = sin_pi_4 * (b7i - b7r);
- b7i = - (b7r + b7i) * sin_pi_4;
- b7r = t;
-
- a0r = b0r + b2r;
- a0i = b0i + b2i;
- a1r = b1r + b3r;
- a1i = b1i + b3i;
- a2r = b0r - b2r;
- a2i = b0i - b2i;
-
- a3r = b1i - b3i;
- a3i = b3r - b1r;
- a4r = b4r + b6r;
- a4i = b4i + b6i;
- a5r = b5r + b7r;
- a5i = b5i + b7i;
- a6r = b4r - b6r;
- a6i = b4i - b6i;
-
- a7r = b5i - b7i;
- a7i = b7r - b5r;
-
-
- output[0] = a0r + a1r;
- output[1] = a0i + a1i;
-
- output[4*stride_out] = a0r - a1r;
- output[4*stride_out+1] = a0i - a1i;
-
- output[2*stride_out] = a2r + a3r;
- output[2*stride_out+1] = a2i + a3i;
-
- output[6*stride_out] = a2r - a3r;
- output[6*stride_out+1] = a2i - a3i;
-
- output[stride_out] = a4r + a5r;
- output[stride_out+1] = a4i + a5i;
-
- output[5*stride_out] = a4r - a5r;
- output[5*stride_out+1] = a4i - a5i;
-
- output[3*stride_out] = a6r + a7r;
- output[3*stride_out+1] = a6i + a7i;
-
- output[7*stride_out] = a6r - a7r;
- output[7*stride_out+1] = a6i - a7i;
- }
- inline void fft4(float *input, int stride_in, float *output, int stride_out)
- {
-
- float t1, t2;
- t1 = input[0] + input[2*stride_in];
- t2 = input[stride_in] + input[3*stride_in];
- output[0] = t1 + t2;
- output[2*stride_out] = t1 - t2;
- t1 = input[1] + input[2*stride_in+1];
- t2 = input[stride_in+1] + input[3*stride_in+1];
- output[1] = t1 + t2;
- output[2*stride_out+1] = t1 - t2;
- t1 = input[0] - input[2*stride_in];
- t2 = input[stride_in+1] - input[3*stride_in+1];
- output[stride_out] = t1 + t2;
- output[3*stride_out] = t1 - t2;
- t1 = input[1] - input[2*stride_in+1];
- t2 = input[3*stride_in] - input[stride_in];
- output[stride_out+1] = t1 + t2;
- output[3*stride_out+1] = t1 - t2;
- }
|