blob: 18b2de70a561b0b563a1333d44e5a42f17ee9da8 [file] [log] [blame]
Tom Tsou35222292016-06-22 16:16:30 -07001/*
2 * Fast Fourier transform
3 *
4 * Copyright (C) 2012 Tom Tsou <tom@tsou.cc>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
18 * See the COPYING file in the main directory for details.
19 */
20
21#include <stdlib.h>
22#include <string.h>
23#include <assert.h>
24#include <fftw3.h>
25
26#include "fft.h"
27
28struct fft_hdl {
29 float *fft_in;
30 float *fft_out;
31 int len;
32 fftwf_plan fft_plan;
33};
34
35/*! \brief Initialize FFT backend
36 * \param[in] reverse FFT direction
37 * \param[in] m FFT length
38 * \param[in] istride input stride count
39 * \param[in] ostride output stride count
40 * \param[in] in input buffer (FFTW aligned)
41 * \param[in] out output buffer (FFTW aligned)
42 * \param[in] ooffset initial offset into output buffer
43 *
44 * If the reverse is non-NULL, then an inverse FFT will be used. This is a
45 * wrapper for advanced non-contiguous FFTW usage. See FFTW documentation for
46 * further details.
47 *
48 * http://www.fftw.org/doc/Advanced-Complex-DFTs.html
49 *
50 * It is currently unknown how the offset of the output buffer affects FFTW
51 * memory alignment.
52 */
53struct fft_hdl *init_fft(int reverse, int m, int istride, int ostride,
54 float *in, float *out, int ooffset)
55{
56 int rank = 1;
57 int n[] = { m };
58 int howmany = istride;
59 int idist = 1;
60 int odist = 1;
61 int *inembed = n;
62 int *onembed = n;
63 fftwf_complex *obuffer, *ibuffer;
64
65 struct fft_hdl *hdl = (struct fft_hdl *) malloc(sizeof(struct fft_hdl));
66 if (!hdl)
67 return NULL;
68
69 int direction = FFTW_FORWARD;
70 if (reverse)
71 direction = FFTW_BACKWARD;
72
73 ibuffer = (fftwf_complex *) in;
74 obuffer = (fftwf_complex *) out + ooffset;
75
76 hdl->fft_in = in;
77 hdl->fft_out = out;
78 hdl->fft_plan = fftwf_plan_many_dft(rank, n, howmany,
79 ibuffer, inembed, istride, idist,
80 obuffer, onembed, ostride, odist,
81 direction, FFTW_MEASURE);
82 return hdl;
83}
84
85void *fft_malloc(size_t size)
86{
87 return fftwf_malloc(size);
88}
89
90void fft_free(void *ptr)
91{
92 free(ptr);
93}
94
95/*! \brief Free FFT backend resources
96 */
97void free_fft(struct fft_hdl *hdl)
98{
99 fftwf_destroy_plan(hdl->fft_plan);
100 free(hdl);
101}
102
103/*! \brief Run multiple DFT operations with the initialized plan
104 * \param[in] hdl handle to an intitialized fft struct
105 *
106 * Input and output buffers are configured with init_fft().
107 */
108int cxvec_fft(struct fft_hdl *hdl)
109{
110 fftwf_execute(hdl->fft_plan);
111 return 0;
112}