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>
31 #include <boost/thread.hpp>
33 typedef boost::mutex::scoped_lock scoped_lock;
34 static boost::mutex s_planning_mutex;
40 static char *filename = ".gr_fftw_wisdom";
42 char *home = getenv ("HOME");
44 char *p = new char[strlen (home) + strlen (filename) + 2];
54 gri_fftw_import_wisdom ()
56 char *filename = wisdom_filename ();
57 FILE *fp = fopen (filename, "r");
59 int r = fftwf_import_wisdom_from_file (fp);
62 fprintf (stderr, "gri_fftw: can't import wisdom from %s\n", filename);
69 gri_fftw_export_wisdom ()
71 char *filename = wisdom_filename ();
72 FILE *fp = fopen (filename, "w");
74 fftwf_export_wisdom_to_file (fp);
78 fprintf (stderr, "gri_fftw: ");
84 // ----------------------------------------------------------------
86 gri_fft_complex::gri_fft_complex (int fft_size, bool forward)
88 // Hold global mutex during plan construction and destruction.
89 scoped_lock lock(s_planning_mutex);
91 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
94 throw std::out_of_range ("gri_fftw: invalid fft_size");
96 d_fft_size = fft_size;
97 d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
99 throw std::runtime_error ("fftwf_malloc");
101 d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
103 fftwf_free (d_inbuf);
104 throw std::runtime_error ("fftwf_malloc");
107 gri_fftw_import_wisdom (); // load prior wisdom from disk
108 d_plan = fftwf_plan_dft_1d (fft_size,
109 reinterpret_cast<fftwf_complex *>(d_inbuf),
110 reinterpret_cast<fftwf_complex *>(d_outbuf),
111 forward ? FFTW_FORWARD : FFTW_BACKWARD,
114 if (d_plan == NULL) {
115 fprintf(stderr, "gri_fft_complex: error creating plan\n");
116 throw std::runtime_error ("fftwf_plan_dft_1d failed");
118 gri_fftw_export_wisdom (); // store new wisdom to disk
121 gri_fft_complex::~gri_fft_complex ()
123 // Hold global mutex during plan construction and destruction.
124 scoped_lock lock(s_planning_mutex);
126 fftwf_destroy_plan ((fftwf_plan) d_plan);
127 fftwf_free (d_inbuf);
128 fftwf_free (d_outbuf);
132 gri_fft_complex::execute ()
134 fftwf_execute ((fftwf_plan) d_plan);
137 // ----------------------------------------------------------------
139 gri_fft_real_fwd::gri_fft_real_fwd (int fft_size)
141 // Hold global mutex during plan construction and destruction.
142 scoped_lock lock(s_planning_mutex);
144 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
147 throw std::out_of_range ("gri_fftw: invalid fft_size");
149 d_fft_size = fft_size;
150 d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ());
152 throw std::runtime_error ("fftwf_malloc");
154 d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ());
156 fftwf_free (d_inbuf);
157 throw std::runtime_error ("fftwf_malloc");
160 gri_fftw_import_wisdom (); // load prior wisdom from disk
161 d_plan = fftwf_plan_dft_r2c_1d (fft_size,
163 reinterpret_cast<fftwf_complex *>(d_outbuf),
166 if (d_plan == NULL) {
167 fprintf(stderr, "gri_fft_real_fwd: error creating plan\n");
168 throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed");
170 gri_fftw_export_wisdom (); // store new wisdom to disk
173 gri_fft_real_fwd::~gri_fft_real_fwd ()
175 // Hold global mutex during plan construction and destruction.
176 scoped_lock lock(s_planning_mutex);
178 fftwf_destroy_plan ((fftwf_plan) d_plan);
179 fftwf_free (d_inbuf);
180 fftwf_free (d_outbuf);
184 gri_fft_real_fwd::execute ()
186 fftwf_execute ((fftwf_plan) d_plan);
189 // ----------------------------------------------------------------
191 gri_fft_real_rev::gri_fft_real_rev (int fft_size)
193 assert (sizeof (fftwf_complex) == sizeof (gr_complex));
196 throw std::out_of_range ("gri_fftw: invalid fft_size");
198 d_fft_size = fft_size;
199 d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ());
201 throw std::runtime_error ("fftwf_malloc");
203 d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ());
205 fftwf_free (d_inbuf);
206 throw std::runtime_error ("fftwf_malloc");
209 // FIXME If there's ever a chance that the planning functions
210 // will be called in multiple threads, we've got to ensure single
211 // threaded access. They are not thread-safe.
213 gri_fftw_import_wisdom (); // load prior wisdom from disk
214 d_plan = fftwf_plan_dft_c2r_1d (fft_size,
215 reinterpret_cast<fftwf_complex *>(d_inbuf),
219 if (d_plan == NULL) {
220 fprintf(stderr, "gri_fft_real_rev: error creating plan\n");
221 throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed");
223 gri_fftw_export_wisdom (); // store new wisdom to disk
226 gri_fft_real_rev::~gri_fft_real_rev ()
228 fftwf_destroy_plan ((fftwf_plan) d_plan);
229 fftwf_free (d_inbuf);
230 fftwf_free (d_outbuf);
234 gri_fft_real_rev::execute ()
236 fftwf_execute ((fftwf_plan) d_plan);