Wayverb
arbitrary_magnitude_filter.h
1 #pragma once
2 
3 #include "waveguide/frequency_domain_envelope.h"
4 
5 #include "core/cosine_interp.h"
6 #include "core/filter_coefficients.h"
7 
8 #include "itpp/signal/filter_design.h"
9 
10 namespace wayverb {
11 namespace waveguide {
12 namespace detail {
13 
14 template <typename It>
15 auto to_itpp_vec(It b, It e) {
16  const auto size = std::distance(b, e);
17  if (0 < size) {
18  itpp::vec ret(size);
19  for (auto i = 0; b != e; ++b, ++i) {
20  ret[i] = *b;
21  }
22  return ret;
23  }
24  return itpp::vec{};
25 }
26 
27 template <size_t... Ix>
28 auto to_array(const itpp::vec& x, std::index_sequence<Ix...>) {
29  return std::array<double, sizeof...(Ix)>{{x[Ix]...}};
30 }
31 
32 template <size_t I>
33 auto to_array(const itpp::vec& x) {
34  if (x.size() != I) {
35  throw std::runtime_error{
36  "ITPP vec cannot be converted to array with specified size."};
37  }
38 
39  return to_array(x, std::make_index_sequence<I>{});
40 }
41 
42 } // namespace detail
43 
45 
46 constexpr auto make_interp_point(const frequency_domain_envelope::point& pt) {
47  struct ret final {
48  double x;
49  double y;
50  };
51  return ret{pt.frequency, pt.amplitude};
52 }
53 
54 template <typename It>
55 constexpr auto make_interp_iterator(It it) {
56  return util::make_mapping_iterator_adapter(std::move(it),
57  make_interp_point);
58 }
59 
63 template <size_t N>
64 auto arbitrary_magnitude_filter(frequency_domain_envelope env) {
65  remove_outside_frequency_range(env, util::make_range(0.0, 1.0));
66  env.insert(frequency_domain_envelope::point{0.0, 0.0});
67  env.insert(frequency_domain_envelope::point{1.0, 0.0});
68 
69  const auto new_envelope = [&] {
70  const auto npts = 256;
71  frequency_domain_envelope ret;
72  for (auto i = 0; i != npts; ++i) {
73  const auto frequency = i / (npts - 1.0);
74  ret.insert(frequency_domain_envelope::point{
75  frequency,
76  interp(make_interp_iterator(env.cbegin()),
77  make_interp_iterator(env.cend()),
78  frequency,
79  core::linear_interp_functor{})});
80  }
81  return ret;
82  }();
83 
84  itpp::vec b;
85  itpp::vec a;
86  yulewalk(N,
87  detail::to_itpp_vec(make_frequency_iterator(new_envelope.cbegin()),
88  make_frequency_iterator(new_envelope.cend())),
89  detail::to_itpp_vec(make_amplitude_iterator(new_envelope.cbegin()),
90  make_amplitude_iterator(new_envelope.cend())),
91  b,
92  a);
93  return core::make_filter_coefficients(detail::to_array<N + 1>(b),
94  detail::to_array<N + 1>(a));
95 }
96 
97 } // namespace waveguide
98 } // namespace wayverb
Definition: traits.h:46
Definition: capsule_base.h:9