3 * Copyright 2003,2008 Free Software Foundation, Inc.
5 * This file is part of GNU Radio
7 * GNU Radio is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
12 * GNU Radio is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with GNU Radio; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
25 #include <gr_complex.h>
34 gri_fft_planner::mutex()
36 static boost::mutex s_planning_mutex;
38 return s_planning_mutex;
44 static const char *filename = ".gr_fftw_wisdom";
46 char *home = getenv ("HOME");
48 char *p = new char[strlen (home) + strlen (filename) + 2];
58 gri_fftw_import_wisdom ()
60 char *filename = wisdom_filename ();
61 FILE *fp = fopen (filename, "r");
63 int r = fftwf_import_wisdom_from_file (fp);
66 fprintf (stderr, "gri_fftw: can't import wisdom from %s\n", filename);
73 gri_fftw_export_wisdom ()
75 char *filename = wisdom_filename ();
76 FILE *fp = fopen (filename, "w");
78 fftwf_export_wisdom_to_file (fp);
82 fprintf (stderr, "gri_fftw: ");
88 // ----------------------------------------------------------------
90 gri_fft_complex::gri_fft_complex (int fft_size, bool forward)
92 // Hold global mutex during plan construction and destruction.
93 gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
95 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
98 throw std::out_of_range ("gri_fftw: invalid fft_size");
100 d_fft_size = fft_size;
101 d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
103 throw std::runtime_error ("fftwf_malloc");
105 d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
107 fftwf_free (d_inbuf);
108 throw std::runtime_error ("fftwf_malloc");
111 gri_fftw_import_wisdom (); // load prior wisdom from disk
112 d_plan = fftwf_plan_dft_1d (fft_size,
113 reinterpret_cast<fftwf_complex *>(d_inbuf),
114 reinterpret_cast<fftwf_complex *>(d_outbuf),
115 forward ? FFTW_FORWARD : FFTW_BACKWARD,
118 if (d_plan == NULL) {
119 fprintf(stderr, "gri_fft_complex: error creating plan\n");
120 throw std::runtime_error ("fftwf_plan_dft_1d failed");
122 gri_fftw_export_wisdom (); // store new wisdom to disk
125 gri_fft_complex::~gri_fft_complex ()
127 // Hold global mutex during plan construction and destruction.
128 gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
130 fftwf_destroy_plan ((fftwf_plan) d_plan);
131 fftwf_free (d_inbuf);
132 fftwf_free (d_outbuf);
136 gri_fft_complex::execute ()
138 fftwf_execute ((fftwf_plan) d_plan);
141 // ----------------------------------------------------------------
143 gri_fft_real_fwd::gri_fft_real_fwd (int fft_size)
145 // Hold global mutex during plan construction and destruction.
146 gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
148 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
151 throw std::out_of_range ("gri_fftw: invalid fft_size");
153 d_fft_size = fft_size;
154 d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ());
156 throw std::runtime_error ("fftwf_malloc");
158 d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
160 fftwf_free (d_inbuf);
161 throw std::runtime_error ("fftwf_malloc");
164 gri_fftw_import_wisdom (); // load prior wisdom from disk
165 d_plan = fftwf_plan_dft_r2c_1d (fft_size,
167 reinterpret_cast<fftwf_complex *>(d_outbuf),
170 if (d_plan == NULL) {
171 fprintf(stderr, "gri_fft_real_fwd: error creating plan\n");
172 throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed");
174 gri_fftw_export_wisdom (); // store new wisdom to disk
177 gri_fft_real_fwd::~gri_fft_real_fwd ()
179 // Hold global mutex during plan construction and destruction.
180 gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
182 fftwf_destroy_plan ((fftwf_plan) d_plan);
183 fftwf_free (d_inbuf);
184 fftwf_free (d_outbuf);
188 gri_fft_real_fwd::execute ()
190 fftwf_execute ((fftwf_plan) d_plan);
193 // ----------------------------------------------------------------
195 gri_fft_real_rev::gri_fft_real_rev (int fft_size)
197 // Hold global mutex during plan construction and destruction.
198 gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex());
200 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
203 throw std::out_of_range ("gri_fftw: invalid fft_size");
205 d_fft_size = fft_size;
206 d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
208 throw std::runtime_error ("fftwf_malloc");
210 d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ());
212 fftwf_free (d_inbuf);
213 throw std::runtime_error ("fftwf_malloc");
216 // FIXME If there's ever a chance that the planning functions
217 // will be called in multiple threads, we've got to ensure single
218 // threaded access. They are not thread-safe.
220 gri_fftw_import_wisdom (); // load prior wisdom from disk
221 d_plan = fftwf_plan_dft_c2r_1d (fft_size,
222 reinterpret_cast<fftwf_complex *>(d_inbuf),
226 if (d_plan == NULL) {
227 fprintf(stderr, "gri_fft_real_rev: error creating plan\n");
228 throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed");
230 gri_fftw_export_wisdom (); // store new wisdom to disk
233 gri_fft_real_rev::~gri_fft_real_rev ()
235 fftwf_destroy_plan ((fftwf_plan) d_plan);
236 fftwf_free (d_inbuf);
237 fftwf_free (d_outbuf);
241 gri_fft_real_rev::execute ()
243 fftwf_execute ((fftwf_plan) d_plan);