fft.cpp
1 /***************************************************************************
2  Copyright (C) 2002-2015 Kentaro Kitagawa
3  kitagawa@phys.s.u-tokyo.ac.jp
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License as published by the Free Software Foundation; either
8  version 2 of the License, or (at your option) any later version.
9 
10  You should have received a copy of the GNU Library General
11  Public License and a list of authors along with this program;
12  see the files COPYING and AUTHORS.
13  ***************************************************************************/
14 #include "fft.h"
15 
16 #include <gsl/gsl_sf.h>
17 #define bessel_i0 gsl_sf_bessel_I0
18 
19 int
20 FFTBase::fitLength(int length0) {
21  int length = lrint(pow(2.0, (ceil(log(length0) / log(2.0)))));
22  length = std::min(length, (int)lrint(pow(2.0, (ceil(log(length0 / 3.0) / log(2.0))))) * 3);
23  length = std::min(length, (int)lrint(pow(2.0, (ceil(log(length0 / 5.0) / log(2.0))))) * 5);
24  length = std::min(length, (int)lrint(pow(2.0, (ceil(log(length0 / 7.0) / log(2.0))))) * 7);
25  length = std::min(length, (int)lrint(pow(2.0, (ceil(log(length0 / 9.0) / log(2.0))))) * 9);
26  assert(length0 <= length);
27 // dbgPrint(formatString("FFT using L=%d\n", length));
28  return length;
29 }
30 
31 double FFTBase::windowFuncRect(double x) {
32  return (fabs(x) <= 0.5) ? 1 : 0;
33 // return 1.0;
34 }
35 double FFTBase::windowFuncTri(double x) {
36  return std::max(0.0, 1.0 - 2.0 * fabs(x));
37 }
38 double FFTBase::windowFuncHanning(double x) {
39  if (fabs(x) >= 0.5)
40  return 0.0;
41  return 0.5 + 0.5*cos(2*M_PI*x);
42 }
43 double FFTBase::windowFuncHamming(double x) {
44  if (fabs(x) >= 0.5)
45  return 0.0;
46  return 0.54 + 0.46*cos(2*M_PI*x);
47 }
48 double FFTBase::windowFuncBlackman(double x) {
49  if (fabs(x) >= 0.5)
50  return 0.0;
51  return 0.42323+0.49755*cos(2*M_PI*x)+0.07922*cos(4*M_PI*x);
52 }
53 double FFTBase::windowFuncBlackmanHarris(double x) {
54  if (fabs(x) >= 0.5)
55  return 0.0;
56  return 0.35875+0.48829*cos(2*M_PI*x)+0.14128*cos(4*M_PI*x)+0.01168*cos(6*M_PI*x);
57 }
58 double FFTBase::windowFuncFlatTop(double x) {
59  return windowFuncHamming(x)*((fabs(x) < 1e-4) ? 1 : sin(4*M_PI*x)/(4*M_PI*x));
60 }
61 double FFTBase::windowFuncKaiser(double x, double alpha) {
62  if (fabs(x) >= 0.5)
63  return 0.0;
64  x *= 2;
65  x = sqrt(std::max(1 - x*x, 0.0));
66  return bessel_i0(M_PI*alpha*x) / bessel_i0(M_PI*alpha);
67 }
68 double FFTBase::windowFuncKaiser1(double x) {
69  return windowFuncKaiser(x, 3.0);
70 }
71 double FFTBase::windowFuncKaiser2(double x) {
72  return windowFuncKaiser(x, 7.2);
73 }
74 double FFTBase::windowFuncKaiser3(double x) {
75  return windowFuncKaiser(x, 15.0);
76 }
77 
78 double FFTBase::windowFuncFlatTopLong(double x) {
79  return windowFuncHamming(x)*((fabs(x) < 1e-4) ? 1 : sin(6*M_PI*x)/(6*M_PI*x));
80 }
81 double FFTBase::windowFuncFlatTopLongLong(double x) {
82  return windowFuncHamming(x)*((fabs(x) < 1e-4) ? 1 : sin(8*M_PI*x)/(8*M_PI*x));
83 }
84 double FFTBase::windowFuncHalfSin(double x) {
85  if (fabs(x) >= 0.5)
86  return 0.0;
87  return cos(M_PI*x);
88 }
89 
90 
91 FFTBase::FFTBase(int length) {
92  m_fftlen = length;
93  m_fftplan.reset(new fftw_plan);
94 }
95 FFTBase::~FFTBase() {
96  fftw_destroy_plan(*m_fftplan);
97 }
98 FFT::FFT(int sign, int length) : FFTBase(length) {
99  m_pBufin = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * length);
100  m_pBufout = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * length);
101  *m_fftplan = fftw_plan_dft_1d(length, m_pBufin, m_pBufout,
102  (sign > 0) ? FFTW_BACKWARD : FFTW_FORWARD, FFTW_ESTIMATE);
103 }
104 FFT::~FFT() {
105  fftw_free(m_pBufin);
106  fftw_free(m_pBufout);
107 }
108 void
109 FFT::exec(const std::vector<std::complex<double> >& wavein,
110  std::vector<std::complex<double> >& waveout) {
111  int size = wavein.size();
112  assert(size == length());
113  waveout.resize(size);
114  const std::complex<double> *pin = &wavein[0];
115  fftw_complex *pout = m_pBufin;
116  for(int i = 0; i < size; i++) {
117  ( *pout)[0] = pin->real();
118  ( *pout)[1] = pin->imag();
119  pout++;
120  pin++;
121  }
122  fftw_execute( *m_fftplan);
123  const fftw_complex *pin2 = m_pBufout;
124  std::complex<double> *pout2 = &waveout[0];
125  for(int i = 0; i < size; i++) {
126  *pout2 = std::complex<double>(( *pin2)[0], ( *pin2)[1]);
127  pout2++;
128  pin2++;
129  }
130 }
131 
132 RFFT::RFFT(int length) : FFTBase(length) {
133  m_pBufin = (double*)fftw_malloc(sizeof(double) * length);
134  m_pBufout = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * (length / 2 + 1));
135  *m_fftplan = fftw_plan_dft_r2c_1d(length, m_pBufin, m_pBufout, FFTW_ESTIMATE);
136 }
137 RFFT::~RFFT() {
138  fftw_free(m_pBufin);
139  fftw_free(m_pBufout);
140 }
141 void
142 RFFT::exec(const std::vector<double>& wavein,
143  std::vector<std::complex<double> >& waveout) {
144  int size = wavein.size();
145  assert(size == length());
146  waveout.resize(size / 2 + 1);
147  const double *pin = &wavein[0];
148  double *pout = m_pBufin;
149  for(int i = 0; i < size; i++) {
150  *pout++ = *pin++;
151  }
152  fftw_execute(*m_fftplan);
153  const fftw_complex *pin2 = m_pBufout;
154  std::complex<double> *pout2 = &waveout[0];
155  for(int i = 0; i < size / 2 + 1; i++) {
156  *pout2 = std::complex<double>(( *pin2)[0], ( *pin2)[1]);
157  pout2++;
158  pin2++;
159  }
160 }
161 
162 RIFFT::RIFFT(int length) : FFTBase(length) {
163  m_pBufin = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * (length / 2 + 1));
164  m_pBufout = (double*)fftw_malloc(sizeof(double) * length);
165  *m_fftplan = fftw_plan_dft_c2r_1d(length, m_pBufin, m_pBufout, FFTW_ESTIMATE);
166 }
167 RIFFT::~RIFFT() {
168  fftw_free(m_pBufin);
169  fftw_free(m_pBufout);
170 }
171 void
172 RIFFT::exec(const std::vector<std::complex<double> >& wavein,
173  std::vector<double>& waveout) {
174  int size = length();
175  assert((int)wavein.size() == length() / 2 + 1);
176  waveout.resize(size);
177  const std::complex<double> *pin = &wavein[0];
178  fftw_complex *pout = m_pBufin;
179  for(int i = 0; i < size / 2 + 1; i++) {
180  ( *pout)[0] = pin->real();
181  ( *pout)[1] = pin->imag();
182  pout++;
183  pin++;
184  }
185  fftw_execute( *m_fftplan);
186  const double *pin2 = m_pBufout;
187  double *pout2 = &waveout[0];
188  for(int i = 0; i < size; i++) {
189  *pout2++ = *pin2++;
190  }
191 }

Generated for KAME4 by  doxygen 1.8.3