MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
ExtractionHelper.cpp
Go to the documentation of this file.
2
5
6namespace MayaFlux::Yantra {
7
8namespace D = Kinesis::Discrete;
9
10std::vector<std::vector<double>> extract_high_energy(
11 const std::vector<std::span<const double>>& channels,
12 double energy_threshold,
13 uint32_t window_size,
14 uint32_t hop_size)
15{
16 std::vector<std::vector<double>> result;
17 result.reserve(channels.size());
18 for (const auto& ch : channels) {
19 if (ch.empty()) {
20 result.emplace_back();
21 continue;
22 }
23 const uint32_t w = std::min(window_size, static_cast<uint32_t>(ch.size()));
24 const uint32_t h = std::max(1U, std::min(hop_size, w / 2));
25 const auto energy = D::rms(ch, D::num_windows(ch.size(), w, h), h, w);
26 std::vector<size_t> starts;
27 for (size_t i = 0; i < energy.size(); ++i) {
28 if (energy[i] > energy_threshold)
29 starts.push_back(i * h);
30 }
31 result.push_back(D::slice_intervals(ch,
33 }
34 return result;
35}
36
37std::vector<std::vector<double>> extract_peaks(
38 const std::vector<std::span<const double>>& channels,
39 double threshold,
40 double min_distance,
41 uint32_t region_size)
42{
43 std::vector<std::vector<double>> result;
44 result.reserve(channels.size());
45 for (const auto& ch : channels) {
46 if (ch.size() < 3) {
47 result.emplace_back();
48 continue;
49 }
50
51 const auto [lo, hi] = std::ranges::minmax_element(ch);
52 if (*hi - *lo < std::numeric_limits<double>::epsilon()) {
53 result.emplace_back();
54 continue;
55 }
56 const auto pos = D::peak_positions(ch, threshold, static_cast<size_t>(min_distance));
57 result.push_back(D::slice_intervals(ch,
58 D::merge_intervals(D::regions_around_positions(pos, region_size / 2, ch.size()))));
59 }
60
61 return result;
62}
63
64std::vector<std::vector<double>> extract_outliers(
65 const std::vector<std::span<const double>>& channels,
66 double std_dev_threshold,
67 uint32_t window_size,
68 uint32_t hop_size)
69{
70 std::vector<std::vector<double>> result;
71 result.reserve(channels.size());
72 for (const auto& ch : channels) {
73 if (ch.empty()) {
74 result.emplace_back();
75 continue;
76 }
77 const uint32_t w = std::min(window_size, static_cast<uint32_t>(ch.size()));
78 const uint32_t h = std::max(1U, std::min(hop_size, w / 2));
79 const size_t nw = D::num_windows(ch.size(), w, h);
80 const auto means = D::mean(ch, nw, h, w);
81
82 if (means.empty()) {
83 result.emplace_back();
84 continue;
85 }
86
87 double gm = 0.0;
88 for (double v : means)
89 gm += v;
90 gm /= static_cast<double>(means.size());
91
92 double var = 0.0;
93 for (double v : means)
94 var += (v - gm) * (v - gm);
95 const double gs = std::sqrt(var / static_cast<double>(means.size()));
96
97 if (gs <= 0.0) {
98 result.emplace_back();
99 continue;
100 }
101
102 std::vector<size_t> starts;
103 for (size_t i = 0; i < means.size(); ++i) {
104 if (std::abs(means[i] - gm) > std_dev_threshold * gs)
105 starts.push_back(i * h);
106 }
107
108 result.push_back(D::slice_intervals(ch,
110 }
111
112 return result;
113}
114
115std::vector<std::vector<double>> extract_high_spectral(
116 const std::vector<std::span<const double>>& channels,
117 double spectral_threshold,
118 uint32_t window_size,
119 uint32_t hop_size)
120{
121 std::vector<std::vector<double>> result;
122 result.reserve(channels.size());
123 for (const auto& ch : channels) {
124 if (ch.empty()) {
125 result.emplace_back();
126 continue;
127 }
128 const uint32_t w = std::min(window_size, static_cast<uint32_t>(ch.size()));
129 const uint32_t h = std::max(1U, std::min(hop_size, w / 2));
130 const auto energy = D::spectral_energy(ch, D::num_windows(ch.size(), w, h), h, w);
131
132 std::vector<size_t> starts;
133 for (size_t i = 0; i < energy.size(); ++i) {
134 if (energy[i] > spectral_threshold)
135 starts.push_back(i * h);
136 }
137
138 result.push_back(D::slice_intervals(ch,
140 }
141 return result;
142}
143
144std::vector<std::vector<double>> extract_above_mean(
145 const std::vector<std::span<const double>>& channels,
146 double mean_multiplier,
147 uint32_t window_size,
148 uint32_t hop_size)
149{
150 std::vector<std::vector<double>> result;
151 result.reserve(channels.size());
152 for (const auto& ch : channels) {
153 if (ch.empty()) {
154 result.emplace_back();
155 continue;
156 }
157 const uint32_t w = std::min(window_size, static_cast<uint32_t>(ch.size()));
158 const uint32_t h = std::max(1U, std::min(hop_size, w / 2));
159 const auto means = D::mean(ch, D::num_windows(ch.size(), w, h), h, w);
160 double gm = 0.0;
161
162 for (double v : means)
163 gm += v;
164
165 if (!means.empty())
166 gm /= static_cast<double>(means.size());
167
168 const double thr = gm * mean_multiplier;
169
170 std::vector<size_t> starts;
171 for (size_t i = 0; i < means.size(); ++i) {
172 if (means[i] > thr)
173 starts.push_back(i * h);
174 }
175
176 result.push_back(D::slice_intervals(ch,
178 }
179 return result;
180}
181
182std::vector<std::vector<double>> extract_overlapping_windows(
183 const std::vector<std::span<const double>>& channels,
184 uint32_t window_size,
185 double overlap)
186{
187 std::vector<std::vector<double>> result;
188 result.reserve(channels.size());
189 for (const auto& ch : channels)
190 result.push_back(D::overlapping_windows(ch, window_size, overlap));
191 return result;
192}
193
194std::vector<std::vector<double>> extract_zero_crossings(
195 const std::vector<std::span<const double>>& channels,
196 double threshold,
197 double min_distance,
198 uint32_t region_size)
199{
200 std::vector<std::vector<double>> result;
201 result.reserve(channels.size());
202 for (const auto& ch : channels) {
203 if (ch.empty() || region_size == 0) {
204 result.emplace_back();
205 continue;
206 }
207 auto all = D::zero_crossing_positions(ch, threshold);
208 std::vector<size_t> filtered;
209 size_t last = 0;
210 for (size_t p : all) {
211 if (filtered.empty() || (p - last) >= static_cast<size_t>(min_distance)) {
212 filtered.push_back(p);
213 last = p;
214 }
215 }
216
217 result.push_back(D::slice_intervals(ch,
218 D::merge_intervals(D::regions_around_positions(filtered, region_size / 2, ch.size()))));
219 }
220 return result;
221}
222
223std::vector<std::vector<double>> extract_silence(
224 const std::vector<std::span<const double>>& channels,
225 double silence_threshold,
226 uint32_t min_duration,
227 uint32_t window_size,
228 uint32_t hop_size)
229{
230 std::vector<std::vector<double>> result;
231 result.reserve(channels.size());
232 for (const auto& ch : channels) {
233 if (ch.empty()) {
234 result.emplace_back();
235 continue;
236 }
237 const uint32_t w = std::min(window_size, static_cast<uint32_t>(ch.size()));
238 const uint32_t h = std::max(1U, std::min(hop_size, w / 2));
239 const auto energy = D::rms(ch, D::num_windows(ch.size(), w, h), h, w);
240 std::vector<size_t> starts;
241 for (size_t i = 0; i < energy.size(); ++i) {
242 if (energy[i] <= silence_threshold && w >= min_duration) {
243 starts.push_back(i * h);
244 }
245 }
246 result.push_back(D::slice_intervals(ch,
248 }
249 return result;
250}
251
252std::vector<std::vector<double>> extract_onsets(
253 const std::vector<std::span<const double>>& channels,
254 double threshold,
255 uint32_t region_size,
256 uint32_t fft_window_size,
257 uint32_t hop_size)
258{
259 std::vector<std::vector<double>> result;
260 result.reserve(channels.size());
261 for (const auto& ch : channels) {
262 if (ch.empty()) {
263 result.emplace_back();
264 continue;
265 }
266 const auto pos = D::onset_positions(ch, fft_window_size, hop_size, threshold);
267 result.push_back(D::slice_intervals(ch,
268 D::merge_intervals(D::regions_around_positions(pos, region_size / 2, ch.size()))));
269 }
270 return result;
271}
272
273} // namespace MayaFlux::Yantra
Discrete sequence analysis primitives for MayaFlux::Kinesis.
Discrete sequence extraction primitives for MayaFlux::Kinesis.
Named multichannel extraction functions for FeatureExtractor.
Eigen::Index overlap
std::vector< double > overlapping_windows(std::span< const double > data, uint32_t window_size, double overlap)
Extract overlapping windows as a flat concatenated vector.
Definition Extract.cpp:83
std::vector< double > mean(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Arithmetic mean per window.
Definition Analysis.cpp:200
std::vector< double > spectral_energy(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Spectral energy per window using Hann-windowed FFT.
Definition Analysis.cpp:133
std::vector< size_t > zero_crossing_positions(std::span< const double > data, double threshold)
Sample indices of zero crossings in the full span.
Definition Analysis.cpp:634
std::vector< std::pair< size_t, size_t > > merge_intervals(const std::vector< std::pair< size_t, size_t > > &intervals)
Merge overlapping or adjacent half-open intervals.
Definition Extract.cpp:14
std::vector< size_t > peak_positions(std::span< const double > data, double threshold, size_t min_distance)
Sample indices of local peak maxima in the full span.
Definition Analysis.cpp:646
std::vector< size_t > onset_positions(std::span< const double > data, uint32_t window_size, uint32_t hop_size, double threshold)
Sample indices of onsets detected via spectral flux.
Definition Analysis.cpp:670
std::vector< std::pair< size_t, size_t > > intervals_from_window_starts(const std::vector< size_t > &window_starts, uint32_t window_size, size_t data_size)
Build [start, end) intervals from window start indices.
Definition Extract.cpp:68
std::vector< double > slice_intervals(std::span< const double > data, const std::vector< std::pair< size_t, size_t > > &intervals)
Copy data from a set of half-open intervals into a flat vector.
Definition Extract.cpp:39
size_t num_windows(size_t data_size, uint32_t window_size, uint32_t hop_size) noexcept
Compute the number of analysis windows for a given data size.
Definition Analysis.hpp:39
std::vector< std::pair< size_t, size_t > > regions_around_positions(const std::vector< size_t > &positions, size_t half_region, size_t data_size)
Build [start, end) intervals centred on a set of positions.
Definition Extract.cpp:52
std::vector< double > rms(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
RMS energy per window.
Definition Analysis.cpp:32
std::vector< std::vector< double > > extract_outliers(const std::vector< std::span< const double > > &channels, double std_dev_threshold, uint32_t window_size, uint32_t hop_size)
std::vector< std::vector< double > > extract_onsets(const std::vector< std::span< const double > > &channels, double threshold, uint32_t region_size, uint32_t fft_window_size, uint32_t hop_size)
std::vector< std::vector< double > > extract_above_mean(const std::vector< std::span< const double > > &channels, double mean_multiplier, uint32_t window_size, uint32_t hop_size)
std::vector< std::vector< double > > extract_high_energy(const std::vector< std::span< const double > > &channels, double energy_threshold, uint32_t window_size, uint32_t hop_size)
std::vector< std::vector< double > > extract_zero_crossings(const std::vector< std::span< const double > > &channels, double threshold, double min_distance, uint32_t region_size)
std::vector< std::vector< double > > extract_peaks(const std::vector< std::span< const double > > &channels, double threshold, double min_distance, uint32_t region_size)
std::vector< std::vector< double > > extract_silence(const std::vector< std::span< const double > > &channels, double silence_threshold, uint32_t min_duration, uint32_t window_size, uint32_t hop_size)
std::vector< std::vector< double > > extract_overlapping_windows(const std::vector< std::span< const double > > &channels, uint32_t window_size, double overlap)
std::vector< std::vector< double > > extract_high_spectral(const std::vector< std::span< const double > > &channels, double spectral_threshold, uint32_t window_size, uint32_t hop_size)