Stochastic Loading Module
filter.h
1 #ifndef _FILTER_H_
2 #define _FILTER_H_
3 
4 #include <memory>
5 #include <stdexcept>
6 #include <vector>
7 #include <ipps.h>
8 
12 namespace signal_processing {
13 
22 std::function<std::vector<std::vector<double>>(int, double)>
24  [](int filter_order,
25  double cutoff_freq) -> std::vector<std::vector<double>> {
26  // Allocated memory for coefficients
27  std::vector<Ipp64f> taps(2 * (filter_order + 1));
28  IppStatus status = ippStsNoErr;
29  int internal_buffer_size;
30 
31  // Calculate required buffer size for internal calculations
32  status = ippsIIRGenGetBufferSize(filter_order, &internal_buffer_size);
33  if (status != ippStsNoErr) {
34  throw std::runtime_error(
35  "\nERROR: in signal_processing::hp_butterworth: Error in buffer size "
36  "calculations\n");
37  }
38 
39  // Divide by 2 to make cutoff frequency match the definition given in MATLAB
40  Ipp8u * internal_calcs = ippsMalloc_8u(internal_buffer_size);
41  status = ippsIIRGenHighpass_64f(cutoff_freq / 2.0, 0, filter_order, taps.data(),
42  ippButterworth, internal_calcs);
43 
44  // Check if filter computation succeeded
45  if (status != ippStsNoErr) {
46  throw std::runtime_error(
47  "\nERROR: in signal_processing::hp_butterworth: Error in coefficient "
48  "calculations\n");
49  }
50 
51  std::vector<double> numerator(filter_order + 1);
52  std::vector<double> denominator(filter_order + 1);
53 
54  for (int i = 0; i < filter_order + 1; ++i) {
55  numerator[i] = taps[i];
56  denominator[i] = taps[i + filter_order + 1];
57  }
58 
59  // Free memory associated with internal calcs
60  ippsFree(internal_calcs);
61 
62  return std::vector<std::vector<double>>{numerator, denominator};
63 };
64 
74 std::function<std::vector<double>(std::vector<double>, std::vector<double>,
75  int, int)>
76  impulse_response = [](const std::vector<double>& numerator_coeffs,
77  const std::vector<double>& denominator_coeffs,
78  int order, int num_samples) -> std::vector<double> {
79  if (numerator_coeffs.size() != denominator_coeffs.size()) {
80  throw std::runtime_error(
81  "\nERROR: in signal_processing::impulse_response: Inputs for numerator "
82  "and denominator coefficients not same length\n");
83  }
84 
85  IppStatus status = ippStsNoErr;
86  int internal_buffer_size;
87  IppsIIRState_64f * filter_state = nullptr;
88  Ipp64f *samples = ippsMalloc_64f(num_samples),
89  *impulse = ippsMalloc_64f(num_samples);
90  std::vector<double> taps(numerator_coeffs.size() + denominator_coeffs.size());
91 
92  // Set all values to zero except first one for impulse
93  impulse[0] = 1.0;
94  for (int i = 1; i < num_samples; ++i) {
95  impulse[i] = 0.0;
96  }
97 
98  // Put filter coefficients into single stack array
99  for (unsigned int i = 0; i < numerator_coeffs.size(); ++i) {
100  taps[i] = numerator_coeffs[i];
101  taps[i + numerator_coeffs.size()] = denominator_coeffs[i];
102  }
103 
104  // Get buffer size required for internal calcs
105  status = ippsIIRGetStateSize_64f(order, &internal_buffer_size);
106  if (status != ippStsNoErr) {
107  throw std::runtime_error(
108  "\nERROR: in signal_processing::impulse_response: Error in buffer size "
109  "calculations\n");
110  }
111 
112  // Allocate memory for internal calcs
113  Ipp8u * internal_calcs = ippsMalloc_8u(internal_buffer_size);
114 
115  // Initialize filter state
116  status = ippsIIRInit_64f(&filter_state, taps.data(), order, nullptr, internal_calcs);
117  if (status != ippStsNoErr) {
118  throw std::runtime_error(
119  "\nERROR: in signal_processing::impulse_response: Error in filter initialization\n");
120  }
121 
122  // Apply filter to impulse
123  status = ippsIIR_64f(impulse, samples, num_samples, filter_state);
124  if (status != ippStsNoErr) {
125  throw std::runtime_error(
126  "\nERROR: in signal_processing::impulse_response: Error in filter application\n");
127  }
128 
129  std::vector<double> sample_vec(num_samples);
130  for (int i = 0; i < num_samples; ++i) {
131  sample_vec[i] = samples[i];
132  }
133 
134  // Free memory used for filtering
135  ippsFree(samples);
136  ippsFree(impulse);
137  ippsFree(internal_calcs);
138 
139  return sample_vec;
140 };
141 } // namespace signal_processing
142 
143 #endif // _FILTER_H_
std::function< std::vector< std::vector< double > >int, double)> hp_butterworth
Definition: filter.h:23
std::function< std::vector< double >std::vector< double >, std::vector< double >, int, int)> impulse_response
Definition: filter.h:76