fir.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 "fir.h"
15 #include "support.h"
16 #include <algorithm>
17 
18 #include "fft.h"
19 
20 FIR::FIR(int taps, double bandwidth, double center) :
21  m_taps(taps), m_bandWidth(bandwidth), m_centerFreq(center) {
22  if(taps < 3) taps = 2;
23  taps = taps/2;
24 
25  int taplen = 2 * taps + 1;
26  m_tapLen = taplen;
27  int fftlen = lrint(pow(2.0, ceil(log(taplen * 5) / log(2.0))));
28  fftlen = std::max(64, fftlen);
29  m_fftLen = fftlen;
30  m_pBufR = (double*)fftw_malloc(sizeof(double) * fftlen);
31  m_pBufC = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * (fftlen / 2 + 1));
32  m_firWnd.resize(fftlen / 2 + 1);
33  m_rdftplan = fftw_plan_dft_r2c_1d(fftlen, m_pBufR, m_pBufC, FFTW_ESTIMATE);
34  m_ridftplan = fftw_plan_dft_c2r_1d(fftlen, m_pBufC, m_pBufR, FFTW_ESTIMATE);
35 
36  double omega = M_PI * bandwidth;
37  for(int i = 0; i < fftlen; i++)
38  m_pBufR[i] = 0.0;
39  double z = 0.0;
40  for(int i = -taps; i <= taps; i++) {
41  double x = i * omega;
42  //sinc(x) * Hamming window
43  double y = (i == 0) ? 1.0 : (sin(x)/x);
44  y *= 0.54 + 0.46*cos(M_PI*(double)i/taps);
45  m_pBufR[(fftlen + i) % fftlen] = y;
46  z += y;
47  }
48  //scaling sum into unity
49  //shift center freq
50  double omega_c = 2 * M_PI * center;
51  for(int i = -taps; i <= taps; i++) {
52  m_pBufR[(fftlen + i) % fftlen] *= cos(omega_c * i) / (z * (double)(fftlen));
53  }
54 
55  fftw_execute(m_rdftplan);
56 
57  for(int i = 0; i < (int)m_firWnd.size(); i++) {
58  m_firWnd[i] = m_pBufC[i][0];
59  }
60 }
61 FIR::~FIR() {
62  fftw_destroy_plan(m_rdftplan);
63  fftw_destroy_plan(m_ridftplan);
64  fftw_free(m_pBufR);
65  fftw_free(m_pBufC);
66 }
67 void
68 FIR::exec(const double *src, double *dst, int len) {
69  for(int ss = 0; ss < len; ss += (int)m_fftLen - m_tapLen * 2) {
70  for(int i = 0; i < m_fftLen; i++) {
71  int j = ss + i - m_tapLen;
72  if(j < 0)
73  j = std::min(-j - 1, len - 1);
74  if(j >= len)
75  j = std::max(2 * len - 1 - j, 0);
76  m_pBufR[i] = src[j];
77  }
78  fftw_execute(m_rdftplan);
79  for(int i = 0; i < (int)m_firWnd.size(); i++) {
80  m_pBufC[i][0] = m_pBufC[i][0] * m_firWnd[i];
81  m_pBufC[i][1] = m_pBufC[i][1] * m_firWnd[i];
82  }
83  fftw_execute(m_ridftplan);
84  for(int i = m_tapLen; i < m_fftLen - m_tapLen; i++) {
85  int j = ss + i - m_tapLen;
86  if((j < 0) || (j >= len))
87  continue;
88  else
89  dst[j] = m_pBufR[i];
90  }
91  }
92 }

Generated for KAME4 by  doxygen 1.8.3