SpectMorph
smdcblocker.hh
1 // This Source Code Form is licensed MPL-2.0: http://mozilla.org/MPL/2.0
2 
3 #pragma once
4 
5 #include <cmath>
6 #include <cassert>
7 
8 namespace SpectMorph {
9 
10 /* 1st/2nd order IIR high pass filter to block DC offset; this is a biquad
11  * filter, however, the b0, b1, b2 are omitted in the design and simplified
12  * in the evaluation of the filter because they are close to integers
13  */
14 class DCBlocker
15 {
16  float a1_ = 0;
17  float a2_ = 0;
18 
19  struct BiquadState
20  {
21  float x1 = 0;
22  float x2 = 0;
23  float y1 = 0;
24  float y2 = 0;
25 
26  void
27  reset()
28  {
29  x1 = 0;
30  x2 = 0;
31  y1 = 0;
32  y2 = 0;
33  }
34  } state_left_, state_right_;
35 
36  float
37  apply_biquad1p (float in, BiquadState& state)
38  {
39  float out = in - state.x1 - a1_ * state.y1;
40  state.x1 = in;
41  state.y1 = out;
42  return out;
43  }
44 
45  float
46  apply_biquad2p (float in, BiquadState& state)
47  {
48  float out = in - 2 * state.x1 + state.x2 - a1_ * state.y1 - a2_ * state.y2;
49  state.x2 = state.x1;
50  state.x1 = in;
51  state.y2 = state.y1;
52  state.y1 = out;
53  return out;
54  }
55 
56  template<int CHANNELS> void
57  process_impl (uint n_samples, float *left, float *right)
58  {
59  assert (order_ != 0);
60 
61  BiquadState sl = state_left_, sr = state_right_;
62 
63  if (order_ == 1)
64  {
65  for (uint i = 0; i < n_samples; i++)
66  {
67  left[i] = apply_biquad1p (left[i], sl);
68  if constexpr (CHANNELS == 2)
69  right[i] = apply_biquad1p (right[i], sr);
70  }
71  }
72  else
73  {
74  for (uint i = 0; i < n_samples; i++)
75  {
76  left[i] = apply_biquad2p (left[i], sl);
77  if constexpr (CHANNELS == 2)
78  right[i] = apply_biquad2p (right[i], sr);
79  }
80  }
81 
82  state_left_ = sl;
83  state_right_ = sr;
84  }
85  int order_ = 0;
86 public:
87  void
88  reset (float freq, float rate, int order)
89  {
90  assert (order == 1 || order == 2);
91 
92  const double k = M_PI * freq / rate;
93 
94  if (order == 1)
95  {
96  a1_ = (k - 1) / (k + 1);
97  a2_ = 0;
98  }
99  else
100  {
101  const double kk = k * k;
102  const double div_factor = 1 / (1 + (k + M_SQRT2) * k);
103 
104  a1_ = 2 * (kk - 1) * div_factor;
105  a2_ = (1 - k * M_SQRT2 + kk) * div_factor;
106  }
107  state_left_.reset();
108  state_right_.reset();
109  order_ = order;
110  }
111  void
112  process (uint n_samples, float *left, float *right = nullptr)
113  {
114  if (right)
115  process_impl<2> (n_samples, left, right);
116  else
117  process_impl<1> (n_samples, left, nullptr);
118  }
119 };
120 
121 } // SpectMorph
Definition: smdcblocker.hh:15