Wayverb
postprocess.h
1 #pragma once
2 
3 #include "waveguide/attenuator.h"
4 #include "waveguide/canonical.h"
5 #include "waveguide/config.h"
6 
7 #include "core/attenuator/hrtf.h"
8 #include "core/attenuator/microphone.h"
9 #include "core/cl/iterator.h"
10 #include "core/cl/scene_structs.h"
11 #include "core/mixdown.h"
12 
13 #include "utilities/map_to_vector.h"
14 
15 namespace wayverb {
16 namespace waveguide {
17 
18 template <typename T>
19 using dereferenced_t = decltype(*std::declval<T>());
20 
21 template <typename T, typename U>
22 constexpr auto dereferenced_type_matches_v =
23  std::is_same<std::decay_t<dereferenced_t<T>>, U>::value;
24 
29 
32 
35 template <typename It,
36  std::enable_if_t<std::is_same<std::decay_t<dereferenced_t<It>>,
37  core::bands_type>::value,
38  int> = 0>
39 auto postprocess(It begin, It end, double sample_rate) {
40  return core::multiband_filter_and_mixdown(
41  begin, end, sample_rate, [](auto it, auto index) {
42  return core::make_cl_type_iterator(std::move(it), index);
43  });
44 }
45 
47 template <typename It,
48  std::enable_if_t<std::is_floating_point<
49  std::decay_t<dereferenced_t<It>>>::value,
50  int> = 0>
51 auto postprocess(It begin, It end, double sample_rate) {
52  return util::aligned::vector<float>(begin, end);
53 }
54 
56 
57 template <typename Method>
58 auto postprocess(const band& band,
59  const Method& method,
60  double acoustic_impedance,
61  double output_sample_rate) {
62  auto attenuated = util::map_to_vector(
63  begin(band.directional),
64  end(band.directional),
65  make_attenuate_mapper(method, acoustic_impedance));
66  const auto ret =
67  postprocess(begin(attenuated), end(attenuated), band.sample_rate);
68 
69  return waveguide::adjust_sampling_rate(ret.data(),
70  ret.size(),
71  band.sample_rate,
72  output_sample_rate);
73 }
74 
75 template <typename Method>
76 auto postprocess(const util::aligned::vector<bandpass_band>& results,
77  const Method& method,
78  double acoustic_impedance,
79  double output_sample_rate) {
80  util::aligned::vector<float> ret;
81 
82  for (const auto& band : results) {
83  auto processed = postprocess(
84  band.band, method, acoustic_impedance, output_sample_rate);
85 
86  const auto cutoff = band.valid_hz / output_sample_rate;
87 
88  // Bandpass based on previous band cutoff.
90  frequency_domain::best_fft_length(processed.size()) << 2};
91 
92  constexpr auto l = 0;
93  constexpr auto width = 0.1;
94 
95  const auto b = begin(processed);
96  const auto e = end(processed);
97  filt.run(b, e, b, [&](auto cplx, auto freq) {
98  return cplx * static_cast<float>(
99  frequency_domain::compute_bandpass_magnitude(
100  freq, cutoff, width, l));
101  });
102 
103  // Add results to ret.
104  ret.resize(std::max(ret.size(), processed.size()), 0.0f);
105  std::transform(b, e, begin(ret), begin(ret), std::plus<>{});
106  }
107 
108  {
109  // DC blocking, just in case...
110  // Won't catch exponential drift, but should get really low
111  // oscillations.
112  constexpr auto dc_block_hz = 10.0;
113  const auto dc_block = dc_block_hz / output_sample_rate;
115  frequency_domain::best_fft_length(ret.size()) << 2};
116  const auto b = begin(ret);
117  const auto e = end(ret);
118  filt.run(b, e, b, [&](auto cplx, auto freq) {
119  return cplx * static_cast<float>(
120  frequency_domain::compute_hipass_magnitude(
121  freq, dc_block, 0.9, 0));
122  });
123  }
124 
125  return ret;
126 }
127 
128 } // namespace waveguide
129 } // namespace wayverb
Structured this way so that I can keep all fftw linkage internal.
Definition: filter.h:12
Definition: capsule_base.h:9