Wayverb
sinc.h
1 #pragma once
2 
3 #include "core/dsp_vector_ops.h"
4 
5 #include "utilities/aligned/vector.h"
6 
7 namespace wayverb {
8 namespace core {
9 
11 template <typename T>
12 T sinc(T t) {
13  if (t == 0) {
14  return 1.0;
15  }
16 
17  T pit = M_PI * t;
18  return sin(pit) / pit;
19 }
20 
22 template <typename T = float>
23 util::aligned::vector<T> sinc_kernel(double cutoff, size_t length) {
24  if (!(length % 2)) {
25  throw std::runtime_error("Length of sinc filter kernel must be odd.");
26  }
27 
28  util::aligned::vector<T> ret(length);
29  for (auto i = 0ul; i != length; ++i) {
30  ret[i] = sinc(2 * cutoff * (i - (length - 1) / 2.0));
31  }
32  return ret;
33 }
34 
35 template <typename T, typename U>
36 void elementwise_multiply(T& a, const U& b) {
37  std::transform(begin(a), end(a), begin(b), begin(a), [](auto i, auto j) {
38  return i * j;
39  });
40 }
41 
43 template <typename T = float>
44 util::aligned::vector<T> blackman(size_t length) {
45  // Holy magic numbers Batman!
46  const auto a0 = 7938.0 / 18608.0;
47  const auto a1 = 9240.0 / 18608.0;
48  const auto a2 = 1430.0 / 18608.0;
49 
50  util::aligned::vector<T> ret(length);
51  for (auto i = 0ul; i != length; ++i) {
52  const auto offset = i / (length - 1.0);
53  ret[i] = (a0 - a1 * cos(2 * M_PI * offset) +
54  a2 * cos(4 * M_PI * offset));
55  }
56  return ret;
57 }
58 
59 template <typename T = float>
60 T hanning_point(double f) {
61  return 0.5 - 0.5 * cos(2 * M_PI * f);
62 }
63 
65 template <typename T = float>
66 util::aligned::vector<T> right_hanning(size_t length) {
67  util::aligned::vector<T> ret(length);
68  for (auto i = 0u; i != length; ++i) {
69  ret[i] = hanning_point(0.5 + (i / (2 * (length - 1.0))));
70  }
71  return ret;
72 }
73 
75 template <typename T = float>
76 util::aligned::vector<T> left_hanning(size_t length) {
77  util::aligned::vector<T> ret(length);
78  for (auto i = 0u; i != length; ++i) {
79  ret[i] = hanning_point(i / (2 * (length - 1.0)));
80  }
81  return ret;
82 }
83 
84 template <typename T = float>
85 util::aligned::vector<T> windowed_sinc_kernel(double cutoff, int length) {
86  const auto window = blackman<T>(length);
87  auto kernel = sinc_kernel<T>(cutoff, length);
88  elementwise_multiply(kernel, window);
89  return kernel;
90 }
91 
94 template <typename T = float>
95 util::aligned::vector<T> lopass_sinc_kernel(double sr,
96  double cutoff,
97  int length) {
98  const auto kernel = windowed_sinc_kernel<T>(cutoff / sr, length);
99  // kernel_normalize(kernel);
100  return kernel;
101 }
102 
105 template <typename T = float>
106 util::aligned::vector<T> hipass_sinc_kernel(double sr,
107  double cutoff,
108  int length) {
109  auto kernel = windowed_sinc_kernel<T>(cutoff / sr, length);
110  std::for_each(begin(kernel), end(kernel), [](auto& i) { i *= -1; });
111  kernel[(length - 1) / 2] += 1;
112  // kernel_normalize(kernel);
113  return kernel;
114 }
115 
116 template <typename T = float>
117 util::aligned::vector<T> bandpass_sinc_kernel(double sr,
118  double lo,
119  double hi,
120  int length) {
121  const auto lop = lopass_sinc_kernel(sr, lo, length);
122  auto kernel = lopass_sinc_kernel(sr, hi, length);
123  std::transform(begin(kernel),
124  end(kernel),
125  lop.begin(),
126  kernel.begin(),
127  [](auto a, auto b) { return a - b; });
128  // kernel_normalize(kernel);
129  return kernel;
130 }
131 
132 } // namespace core
133 } // namespace wayverb
Definition: traits.cpp:2
Definition: capsule_base.h:9