Wayverb
histogram.h
1 #pragma once
2 
3 #include "core/sinc.h"
4 
5 #include "utilities/aligned/vector.h"
6 #include "utilities/mapping_iterator_adapter.h"
7 
8 #include <iostream>
9 
10 namespace wayverb {
11 namespace raytracer {
12 
13 template <typename T>
14 constexpr auto time(const T& t) {
15  return t.time;
16 }
17 
18 template <typename T>
19 constexpr auto volume(const T& t) {
20  return t.volume;
21 }
22 
23 template <typename T>
24 struct item_with_time final {
25  T item;
26  double time;
27 };
28 
29 template <typename T>
30 constexpr auto make_item_with_time(T item, double time) {
31  return item_with_time<T>{std::move(item), time};
32 }
33 
34 template <typename T>
35 constexpr auto volume(const item_with_time<T>& t) {
36  return volume(t.item);
37 }
38 
39 struct histogram_mapper final {
40  double speed_of_sound;
41 
42  template <typename T>
43  auto operator()(const T& i) const {
44  return make_item_with_time(i, i.distance / speed_of_sound);
45  }
46 };
47 
48 struct time_functor final {
49  template <typename T>
50  constexpr auto operator()(const T& t) const {
51  return time(t);
52  }
53 };
54 
55 template <typename T, typename Alloc>
56 void resize_if_necessary(std::vector<T, Alloc>& t, size_t new_size) {
57  if (t.size() < new_size) {
58  t.resize(new_size);
59  }
60 }
61 
62 template <typename Ret, typename It, typename T>
63 void incremental_histogram(
64  Ret& ret, It b, It e, double sample_rate, const T& callback) {
65  if (std::distance(b, e)) {
66  const auto make_time_iterator = [](auto it) {
67  return util::make_mapping_iterator_adapter(std::move(it),
68  time_functor{});
69  };
70  const auto max_time_in_input =
71  *std::max_element(make_time_iterator(b), make_time_iterator(e));
72 
73  resize_if_necessary(ret,
74  std::floor(max_time_in_input * sample_rate) + 1);
75 
76  for (; b != e; ++b) {
77  callback(*b, sample_rate, ret);
78  }
79  }
80 }
81 
82 template <typename It, typename T>
83 auto histogram(It b, It e, double sample_rate, const T& callback) {
84  using value_type = decltype(volume(*b));
85  util::aligned::vector<value_type> ret{};
86  incremental_histogram(ret, b, e, sample_rate, callback);
87  return ret;
88 }
89 
90 template <typename T, typename U, typename Alloc>
91 void dirac_sum(const T& item, double sample_rate, std::vector<U, Alloc>& ret) {
92  ret[time(item) * sample_rate] += volume(item);
93 }
94 
95 struct dirac_sum_functor final {
96  template <typename T, typename Ret>
97  void operator()(const T& item, double sample_rate, Ret& ret) const {
98  dirac_sum(item, sample_rate, ret);
99  }
100 };
101 
103 struct sinc_sum_functor final {
104  template <typename T, typename Ret>
105  void operator()(const T& item, double sample_rate, Ret& ret) const {
106  constexpr auto width = 400; // Impulse width in samples.
107 
108  const auto item_time = time(item);
109  const auto centre_sample = item_time * sample_rate;
110 
111  const ptrdiff_t ideal_begin = std::floor(centre_sample - width / 2);
112  const ptrdiff_t ideal_end = std::ceil(centre_sample + width / 2);
113  ret.resize(std::max(ret.size(), static_cast<size_t>(ideal_end)));
114 
115  const auto begin_samp =
116  std::max(static_cast<ptrdiff_t>(0), ideal_begin);
117  const auto end_samp =
118  std::min(static_cast<ptrdiff_t>(ret.size()), ideal_end);
119 
120  for (auto it = ret.begin() + begin_samp,
121  end_it = ret.begin() + end_samp;
122  it != end_it;
123  ++it) {
124  const auto this_sample = std::distance(ret.begin(), it);
125  const auto relative_sample = this_sample - centre_sample;
126  const auto envelope =
127  0.5 * (1 + std::cos(2 * M_PI * relative_sample / width));
128  const auto filt = core::sinc(relative_sample);
129  *it += volume(item) * envelope * filt;
130  }
131  }
132 };
133 
135 
137 
138 template <typename T>
139 auto make_histogram_iterator(T t, double speed_of_sound) {
140  if (speed_of_sound < 300 || 400 <= speed_of_sound) {
141  throw std::runtime_error{"Speed_of_sound outside expected range."};
142  }
143  return util::make_mapping_iterator_adapter(
144  std::move(t), histogram_mapper{speed_of_sound});
145 }
146 
147 } // namespace raytracer
148 } // namespace wayverb
Definition: histogram.h:39
See fu2015 2.2.2 &#39;Discrete form of the impulse response&#39;.
Definition: histogram.h:103
Definition: histogram.h:95
Definition: histogram.h:24
Definition: pressure.h:22
Definition: capsule_base.h:9
Definition: histogram.h:48