3 #include "frequency_domain/envelope.h" 4 #include "frequency_domain/filter.h" 6 #include "utilities/foldl.h" 7 #include "utilities/map.h" 8 #include "utilities/map_to_vector.h" 9 #include "utilities/mapping_iterator_adapter.h" 10 #include "utilities/range.h" 16 std::array<double, N> edges;
21 constexpr
auto make_edges_and_width_factor(
const std::array<double, N>& edges,
22 double width_factor) {
29 return make_edges_and_width_factor(band_edges<N>(audible_range),
30 width_factor(audible_range, N, overlap));
36 size_t next_power_of_two(T t) {
37 return std::ceil(std::log2(t));
41 size_t best_fft_length(T t) {
42 return std::pow(2, next_power_of_two(t));
47 template <
size_t bands_plus_one,
typename It,
typename Callback>
48 auto multiband_filter(It b,
51 const Callback& callback,
53 constexpr
auto bands = bands_plus_one - 1;
57 const auto bins = best_fft_length(std::distance(b, e)) << 2;
61 std::array<double, bands> summed_squared{};
62 std::array<double, bands> integrated_envelopes{};
64 for (
auto i = 0ul; i != bands; ++i) {
65 const auto mapping_b = callback(b, i);
66 const auto mapping_e = callback(e, i);
67 filt.run(mapping_b, mapping_e, mapping_b, [&](
auto cplx,
auto freq) {
68 const auto amp = compute_bandpass_magnitude(
70 util::make_range(params.edges[i + 0], params.edges[i + 1]),
73 integrated_envelopes[i] += amp;
74 const auto ret = cplx *
static_cast<float>(amp);
75 const auto abs_ret = std::abs(ret);
76 summed_squared[i] += abs_ret * abs_ret;
81 std::array<double, bands> normalized_rms{};
82 for (
auto i = 0; i != bands; ++i) {
83 normalized_rms[i] = integrated_envelopes[i] ?
84 std::sqrt(summed_squared[i] / integrated_envelopes[i]) : 0;
87 return normalized_rms;
90 template <
typename It>
91 auto square_sum(It b, It e) {
92 return std::accumulate(
93 b, e, std::decay_t<decltype(*b)>(), [](
auto a,
auto b) {
98 template <
typename It>
99 auto rms(It b, It e) {
101 return sqrt(square_sum(b, e));
104 template <
size_t bands,
typename T>
105 auto init_array(
const T& t) {
106 std::array<T, bands> ret{};
107 std::fill(begin(ret), end(ret), t);
111 template <
size_t bands,
typename It>
112 auto make_multiband(It begin, It end) {
113 return util::map_to_vector(
114 begin, end, [](
const auto& i) {
return init_array<bands>(i); });
119 constexpr
explicit indexer(
size_t index)
122 template <
typename T>
123 constexpr
auto& operator()(T& t)
const {
127 template <
typename T>
128 constexpr
const auto& operator()(
const T& t)
const {
137 template <
typename It>
138 constexpr
auto operator()(It it,
size_t index)
const {
139 return util::make_mapping_iterator_adapter(std::move(it),
144 template <
size_t bands_plus_one,
typename It>
145 auto per_band_energy(It begin,
148 constexpr
auto bands = bands_plus_one - 1;
150 auto multiband = make_multiband<bands>(begin, end);
152 const auto rms = multiband_filter(std::begin(multiband),
Structured this way so that I can keep all fftw linkage internal.
Definition: filter.h:12
Definition: multiband_filter.h:15
Definition: multiband_filter.h:136
Definition: multiband_filter.h:117