gtkIOStream  1.7.0
GTK+ << C++ IOStream operators for GTK+. Now with ORBing, numerical computation, audio client and more ...
FIR.H
Go to the documentation of this file.
1 /* Copyright 2000-2018 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16 */
17 
18 #ifndef FIR_H
19 #define FIR_H
20 
21 // Debug
22 #include "Debug.H"
23 #pragma GCC diagnostic push
24 #pragma GCC diagnostic ignored "-Wignored-attributes"
25 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
26 #include <Eigen/Dense>
27 #include <unsupported/Eigen/FFT>
28 #pragma GCC diagnostic pop
29 
30 #define FIR_BLOCKSIZE_MISMATCH_ERROR FIR_ERROR_OFFSET-1
31 #define FIR_H_EMPTY_ERROR FIR_ERROR_OFFSET-2
32 #define FIR_CHANNEL_MISMATCH_ERROR FIR_ERROR_OFFSET-3
33 
36 class FIRDebug : virtual public Debug {
37 public:
39 #ifndef NDEBUG
40 errors[FIR_BLOCKSIZE_MISMATCH_ERROR]=std::string("The input data was not of the same length you used as the variable for the method init. ");
41 errors[FIR_H_EMPTY_ERROR]=std::string("The fileter h is empty, please load using loadTimeDomainCoefficients. ");
42 errors[FIR_CHANNEL_MISMATCH_ERROR]=std::string("The input, output and h columns (channels) are not the same count. ");
43 
44 #endif // NDEBUG
45  }
46 };
47 
48 #ifndef FP_TYPE
49 typedef double FP_TYPE;
50 #endif
51 
61 class FIR {
62  Eigen::FFT<FP_TYPE> fft;
63  Eigen::Array<Eigen::FFT<FP_TYPE>::Complex, Eigen::Dynamic, Eigen::Dynamic> H;
64  Eigen::Matrix<FP_TYPE, Eigen::Dynamic, Eigen::Dynamic> h;
65  Eigen::Matrix<FP_TYPE, Eigen::Dynamic, Eigen::Dynamic> x;
66  Eigen::Matrix<FP_TYPE, Eigen::Dynamic, 1> yTemp;
67  Eigen::Array<Eigen::FFT<FP_TYPE>::Complex, Eigen::Dynamic, 1> Y;
68 
71  void resetDFT();
72 protected:
73  unsigned int N;
74  Eigen::Matrix<FP_TYPE, Eigen::Dynamic, Eigen::Dynamic> y;
75 public:
76  FIR(){N=0;}
77 
81  void init(unsigned int blockSize);
82 
88  int loadTimeDomainCoefficients(const std::string fileName);
89 
94  void loadTimeDomainCoefficients(const Eigen::Matrix<FP_TYPE, Eigen::Dynamic, Eigen::Dynamic> hIn);
95 
101  template<typename Derived, typename DerivedOther>
102  void filter(const Eigen::MatrixBase<Derived> &input, Eigen::DenseBase<DerivedOther> const &output) {
103  if (input.rows()!=N){
104  FIRDebug().evaluateError(FIR_BLOCKSIZE_MISMATCH_ERROR);
105  return;
106  }
107  if (input.cols()!=h.cols() || output.cols() != h.cols()){
108  FIRDebug().evaluateError(FIR_CHANNEL_MISMATCH_ERROR);
109  return;
110  }
111  if (h.rows()==0) {
112  FIRDebug().evaluateError(FIR_H_EMPTY_ERROR);
113  return;
114  }
115 
116  if (x.cols() != input.cols()){ // resize if necessary
117  x.setZero(h.rows(), input.cols());
118  y.setZero(h.rows(), input.cols());
119  }
120  y.topRows(y.rows()-N)=y.bottomRows(y.rows()-N); // keep the residual
121  y.bottomRows(N).setZero();
122 
123  x.topRows(N)=input;
124 
125  for (int i=0; i<x.cols(); i++){ // perform the filter on each column
126  fft.fwd(Y.data(), x.col(i).data(), x.rows()); // find the DFT of X=Z=dft(x) (store in Y)
127  Y*=H.col(i); // convolve X (which is Y) with H
128  fft.inv(yTemp.data(), Y.data(), Y.rows()); // take back to the time domain
129  y.col(i)+=yTemp; // add to the residual
130  }
131  const_cast< Eigen::DenseBase<DerivedOther>& >(output)=y.topRows(N);
132  }
133 };
134 #endif // FIR_H
Definition: FIR.H:36
int N
void filter(const Eigen::MatrixBase< Derived > &input, Eigen::DenseBase< DerivedOther > const &output)
Definition: FIR.H:102
Eigen::Matrix< FP_TYPE, Eigen::Dynamic, Eigen::Dynamic > x
the time domain signal for filtering
Definition: FIR.H:65
std::map< int, std::string > errors
This will contain a map between error numbers and descriptive std::strings for the errors...
Definition: Debug.H:115
Eigen::Matrix< FP_TYPE, Eigen::Dynamic, Eigen::Dynamic > h
the time domain representation of the filter
Definition: FIR.H:64
Definition: FIR.H:61
Eigen::Array< Eigen::FFT< FP_TYPE >::Complex, Eigen::Dynamic, Eigen::Dynamic > H
The DFT of the FIR coefficients.
Definition: FIR.H:63
Eigen::Matrix< FP_TYPE, Eigen::Dynamic, Eigen::Dynamic > y
the time domain output signal
Definition: FIR.H:74
Eigen::Matrix< FP_TYPE, Eigen::Dynamic, 1 > yTemp
the time domain signal for filtering
Definition: FIR.H:66
#define FIR_CHANNEL_MISMATCH_ERROR
Definition: FIR.H:32
FIR()
Constructor.
Definition: FIR.H:76
Eigen::FFT< FP_TYPE > fft
The fast Fourier transform.
Definition: FIR.H:62
Definition: Debug.H:112
double FP_TYPE
Internal processing type.
Definition: FIR.H:49
FIRDebug()
Definition: FIR.H:38
#define FIR_H_EMPTY_ERROR
Definition: FIR.H:31
Eigen::Array< Eigen::FFT< FP_TYPE >::Complex, Eigen::Dynamic, 1 > Y
the time domain filter output and also the DFT of one col of x
Definition: FIR.H:67
unsigned int N
Block size of the audio subsystem.
Definition: FIR.H:73
#define FIR_BLOCKSIZE_MISMATCH_ERROR
Definition: FIR.H:30
gtkIOStream: /tmp/gtkiostream/include/DSP/FIR.H Source File
GTK+ IOStream  Beta