MayaFlux 0.3.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Yantra.cpp
Go to the documentation of this file.
1#include "Yantra.hpp"
2
9
11
12namespace MayaFlux {
13
14static bool is_same_size(const std::vector<std::span<double>>& data)
15{
16 if (data.empty())
17 return true;
18
19 const auto expected_size = data.front().size();
20 return std::ranges::all_of(data,
21 [&expected_size](const auto& v) { return v.size() == expected_size; });
22}
23
24static std::vector<double> concat_vectors(const std::vector<std::span<double>>& data)
25{
26 std::vector<double> result;
27 result.reserve(std::accumulate(
28 data.begin(), data.end(), size_t(0),
29 [](size_t sum, const auto& span) { return sum + span.size(); }));
30
31 for (const auto& span : data) {
32 result.insert(result.end(), span.begin(), span.end());
33 }
34 return result;
35}
36
37//=========================================================================
38// STATISTICAL ANALYSIS - Use StatisticalAnalyzer
39//=========================================================================
40
41double mean(const std::vector<double>& data)
42{
43 auto analyzer = std::make_shared<Yantra::StatisticalAnalyzer<>>();
44 analyzer->set_method(Yantra::StatisticalMethod::MEAN);
45 auto result = analyzer->analyze_statistics({ Kakshya::DataVariant(data) });
46 return result.channel_statistics[0].mean_stat;
47}
48
49double mean(const Kakshya::DataVariant& data)
50{
51 auto analyzer = std::make_shared<Yantra::StatisticalAnalyzer<>>();
52 analyzer->set_method(Yantra::StatisticalMethod::MEAN);
53 auto result = analyzer->analyze_statistics({ data });
54 return result.channel_statistics[0].mean_stat;
55}
56
57std::vector<double> mean_per_channel(const std::vector<Kakshya::DataVariant>& data)
58{
59 auto analyzer = std::make_shared<Yantra::StatisticalAnalyzer<>>();
60 analyzer->set_method(Yantra::StatisticalMethod::MEAN);
61 auto result = analyzer->analyze_statistics({ data });
62
63 std::vector<double> means;
64 means.reserve(result.channel_statistics.size());
65
66 for (const auto& stats : result.channel_statistics) {
67 means.push_back(stats.mean_stat);
68 }
69 return means;
70}
71
72double mean_combined(const std::vector<Kakshya::DataVariant>& channels)
73{
75 if (is_same_size(data)) {
76 auto result = mean_per_channel(channels);
77 return std::accumulate(result.begin(), result.end(), 0.0) / result.size();
78 } else {
79 auto mixed = concat_vectors(data);
80 return mean(mixed);
81 }
82}
83
84double rms(const std::vector<double>& data)
85{
86 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
87 analyzer->set_method(Yantra::StatisticalMethod::RMS);
88 auto result = analyzer->analyze_statistics({ Kakshya::DataVariant(data) });
89 return result.channel_statistics[0].statistical_values.empty() ? 0.0 : result.channel_statistics[0].statistical_values[0];
90}
91
92double rms(const Kakshya::DataVariant& data)
93{
94 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
95 analyzer->set_method(Yantra::StatisticalMethod::RMS);
96 auto result = analyzer->analyze_statistics({ data });
97 return result.channel_statistics[0].statistical_values.empty() ? 0.0 : result.channel_statistics[0].statistical_values[0];
98}
99
100std::vector<double> rms_per_channel(const std::vector<Kakshya::DataVariant>& channels)
101{
102 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
103 analyzer->set_method(Yantra::StatisticalMethod::RMS);
104 auto result = analyzer->analyze_statistics(channels);
105 std::vector<double> rms_values;
106 for (const auto& stats : result.channel_statistics) {
107 rms_values.push_back(stats.statistical_values.empty() ? 0.0 : stats.statistical_values[0]);
108 }
109 return rms_values;
110}
111
112double rms_combined(const std::vector<Kakshya::DataVariant>& channels)
113{
115 if (is_same_size(data)) {
116 auto result = rms_per_channel(channels);
117 double sum_squares = 0.0;
118 for (double rms_val : result) {
119 sum_squares += rms_val * rms_val;
120 }
121 return std::sqrt(sum_squares / result.size());
122 } else {
123 auto mixed = concat_vectors(data);
124 return rms(mixed);
125 }
126}
127
128double std_dev(const std::vector<double>& data)
129{
130 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
131 analyzer->set_method(Yantra::StatisticalMethod::STD_DEV);
132 auto result = analyzer->analyze_statistics({ Kakshya::DataVariant(data) });
133 return result.channel_statistics[0].stat_std_dev;
134}
135
136double std_dev(const Kakshya::DataVariant& data)
137{
138 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
139 analyzer->set_method(Yantra::StatisticalMethod::STD_DEV);
140 auto result = analyzer->analyze_statistics({ data });
141 return result.channel_statistics[0].stat_std_dev;
142}
143
144std::vector<double> std_dev_per_channel(const std::vector<Kakshya::DataVariant>& channels)
145{
146 auto analyzer = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
147 analyzer->set_method(Yantra::StatisticalMethod::STD_DEV);
148 auto result = analyzer->analyze_statistics(channels);
149 std::vector<double> std_devs;
150 for (const auto& stats : result.channel_statistics) {
151 std_devs.push_back(stats.stat_std_dev);
152 }
153 return std_devs;
154}
155
156double std_dev_combined(const std::vector<Kakshya::DataVariant>& channels)
157{
159 if (is_same_size(data)) {
160 auto result = std_dev_per_channel(channels);
161 return std::accumulate(result.begin(), result.end(), 0.0) / result.size();
162 } else {
163 auto mixed = concat_vectors(data);
164 return std_dev(mixed);
165 }
166}
167
168double dynamic_range(const std::vector<double>& data)
169{
170 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
171 analyzer->set_energy_method(Yantra::EnergyMethod::DYNAMIC_RANGE);
172 auto result = analyzer->analyze_energy({ Kakshya::DataVariant(data) });
173 return result.channels.empty() || result.channels[0].energy_values.empty() ? 0.0 : result.channels[0].energy_values[0];
174}
175
177{
178 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
179 analyzer->set_energy_method(Yantra::EnergyMethod::DYNAMIC_RANGE);
180 auto result = analyzer->analyze_energy({ data });
181 return result.channels.empty() || result.channels[0].energy_values.empty() ? 0.0 : result.channels[0].energy_values[0];
182}
183
184std::vector<double> dynamic_range_per_channel(const std::vector<Kakshya::DataVariant>& channels)
185{
186 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
187 analyzer->set_energy_method(Yantra::EnergyMethod::DYNAMIC_RANGE);
188 auto result = analyzer->analyze_energy(channels);
189 std::vector<double> ranges;
190 for (const auto& channel : result.channels) {
191 ranges.push_back(channel.energy_values.empty() ? 0.0 : channel.energy_values[0]);
192 }
193 return ranges;
194}
195
196double dynamic_range_global(const std::vector<Kakshya::DataVariant>& channels)
197{
199 double global_min = std::numeric_limits<double>::max();
200 double global_max = std::numeric_limits<double>::lowest();
201
202 for (const auto& span : data) {
203 auto [min_it, max_it] = std::ranges::minmax_element(span);
204 if (min_it != span.end()) {
205 global_min = std::min(global_min, *min_it);
206 global_max = std::max(global_max, *max_it);
207 }
208 }
209
210 if (global_min <= 0.0 || global_max <= 0.0) {
211 return 0.0;
212 }
213 return 20.0 * std::log10(global_max / std::abs(global_min));
214}
215
216double peak(const std::vector<double>& data)
217{
218 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
219 analyzer->set_energy_method(Yantra::EnergyMethod::PEAK);
220 auto result = analyzer->analyze_energy({ Kakshya::DataVariant(data) });
221 return result.channels.empty() ? 0.0 : result.channels[0].max_energy;
222}
223
224double peak(const Kakshya::DataVariant& data)
225{
226 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
227 analyzer->set_energy_method(Yantra::EnergyMethod::PEAK);
228 auto result = analyzer->analyze_energy({ data });
229 return result.channels.empty() ? 0.0 : result.channels[0].max_energy;
230}
231
232double peak(const std::vector<Kakshya::DataVariant>& channels)
233{
234 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
235 analyzer->set_energy_method(Yantra::EnergyMethod::PEAK);
236 auto result = analyzer->analyze_energy(channels);
237 double global_peak = 0.0;
238 for (const auto& channel : result.channels) {
239 global_peak = std::max(global_peak, channel.max_energy);
240 }
241 return global_peak;
242}
243
244std::vector<double> peak_per_channel(const std::vector<Kakshya::DataVariant>& channels)
245{
246 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
247 analyzer->set_energy_method(Yantra::EnergyMethod::PEAK);
248 auto result = analyzer->analyze_energy(channels);
249 std::vector<double> peaks;
250 for (const auto& channel : result.channels) {
251 peaks.push_back(channel.max_energy);
252 }
253 return peaks;
254}
255
256double peak_channel(const std::vector<Kakshya::DataVariant>& channels, size_t channel_index)
257{
258 if (channel_index >= channels.size()) {
259 throw std::out_of_range("Channel index out of range");
260 }
261 return peak(channels[channel_index]);
262}
263
264//=========================================================================
265// FEATURE EXTRACTION - Use FeatureExtractor to get ACTUAL data
266//=========================================================================
267
268std::vector<size_t> zero_crossings(const std::vector<double>& data, double threshold)
269{
270 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
271 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
272
273 auto result = analyzer->analyze_energy({ { data } });
274
275 if (result.channels.empty()) {
276 return {};
277 }
278
279 const auto& positions = result.channels[0].event_positions;
280
281 if (threshold <= 0.0) {
282 return positions;
283 }
284
285 std::vector<size_t> filtered;
286 for (size_t pos : positions) {
287 if (pos < data.size() && std::abs(data[pos]) >= threshold) {
288 filtered.push_back(pos);
289 }
290 }
291 return filtered;
292}
293
294std::vector<size_t> zero_crossings(const Kakshya::DataVariant& data, double threshold)
295{
296 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
297 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
298
299 auto result = analyzer->analyze_energy({ data });
300
301 if (result.channels.empty()) {
302 return {};
303 }
304
305 const auto& positions = result.channels[0].event_positions;
306
307 if (threshold <= 0.0) {
308 return positions;
309 }
310
311 auto double_data = std::get<std::vector<double>>(data);
312 std::vector<size_t> filtered;
313 for (size_t pos : positions) {
314 if (pos < double_data.size() && std::abs(double_data[pos]) >= threshold) {
315 filtered.push_back(pos);
316 }
317 }
318 return filtered;
319}
320
321std::vector<std::vector<size_t>> zero_crossings_per_channel(const std::vector<Kakshya::DataVariant>& channels, double threshold)
322{
323 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
324 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
325 auto result = analyzer->analyze_energy(channels);
326
327 std::vector<std::vector<size_t>> all_crossings;
328 all_crossings.reserve(result.channels.size());
329
330 for (size_t ch = 0; ch < result.channels.size(); ++ch) {
331 const auto& positions = result.channels[ch].event_positions;
332
333 if (threshold <= 0.0) {
334 all_crossings.push_back(positions);
335 continue;
336 }
337
338 auto double_data = std::get<std::vector<double>>(channels[ch]);
339 std::vector<size_t> filtered;
340 for (size_t pos : positions) {
341 if (pos < double_data.size() && std::abs(double_data[pos]) >= threshold) {
342 filtered.push_back(pos);
343 }
344 }
345 all_crossings.push_back(filtered);
346 }
347
348 return all_crossings;
349}
350
351double zero_crossing_rate(const std::vector<double>& data, size_t window_size)
352{
353 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
354 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
355 if (window_size > 0) {
356 analyzer->set_window_parameters(window_size, window_size / 2);
357 }
358 auto result = analyzer->analyze_energy({ Kakshya::DataVariant(data) });
359 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
360}
361
362double zero_crossing_rate(const Kakshya::DataVariant& data, size_t window_size)
363{
364 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
365 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
366 if (window_size > 0) {
367 analyzer->set_window_parameters(window_size, window_size / 2);
368 }
369 auto result = analyzer->analyze_energy({ data });
370 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
371}
372
373std::vector<double> zero_crossing_rate_per_channel(const std::vector<Kakshya::DataVariant>& channels, size_t window_size)
374{
375 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
376 analyzer->set_energy_method(Yantra::EnergyMethod::ZERO_CROSSING);
377 if (window_size > 0) {
378 analyzer->set_window_parameters(window_size, window_size / 2);
379 }
380 auto result = analyzer->analyze_energy(channels);
381
382 std::vector<double> rates;
383 for (const auto& channel : result.channels) {
384 rates.push_back(channel.mean_energy);
385 }
386 return rates;
387}
388
389double spectral_centroid(const std::vector<double>& data, double sample_rate)
390{
391 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
392 analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
393 analyzer->set_parameter("sample_rate", sample_rate);
394 auto result = analyzer->analyze_energy({ Kakshya::DataVariant(data) });
395 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
396}
397
398double spectral_centroid(const Kakshya::DataVariant& data, double sample_rate)
399{
400 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
401 analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
402 analyzer->set_parameter("sample_rate", sample_rate);
403 auto result = analyzer->analyze_energy({ data });
404 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
405}
406
407std::vector<double> spectral_centroid_per_channel(const std::vector<Kakshya::DataVariant>& channels, double sample_rate)
408{
409 auto analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
410 analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
411 analyzer->set_parameter("sample_rate", sample_rate);
412 auto result = analyzer->analyze_energy(channels);
413
414 std::vector<double> centroids;
415 for (const auto& channel : result.channels) {
416 centroids.push_back(channel.mean_energy);
417 }
418 return centroids;
419}
420
421std::vector<double> detect_onsets(const std::vector<double>& data, double sample_rate, double threshold)
422{
423 std::span<const double> data_span(data.data(), data.size());
424
425 auto onset_sample_positions = Kinesis::Discrete::onset_positions(
426 data_span,
427 1024,
428 512,
429 threshold);
430
431 std::vector<double> onset_times;
432 onset_times.reserve(onset_sample_positions.size());
433 for (size_t sample_pos : onset_sample_positions) {
434 onset_times.push_back(static_cast<double>(sample_pos) / sample_rate);
435 }
436
437 return onset_times;
438}
439
440std::vector<double> detect_onsets(const Kakshya::DataVariant& data, double sample_rate, double threshold)
441{
442 auto double_data = std::get<std::vector<double>>(data);
443 std::span<const double> data_span(double_data.data(), double_data.size());
444
445 auto onset_sample_positions = Kinesis::Discrete::onset_positions(
446 data_span,
447 1024,
448 512,
449 threshold);
450
451 std::vector<double> onset_times;
452 onset_times.reserve(onset_sample_positions.size());
453 for (size_t sample_pos : onset_sample_positions) {
454 onset_times.push_back(static_cast<double>(sample_pos) / sample_rate);
455 }
456
457 return onset_times;
458}
459
460std::vector<std::vector<double>> detect_onsets_per_channel(const std::vector<Kakshya::DataVariant>& channels, double sample_rate, double threshold)
461{
462 std::vector<std::vector<double>> all_onsets;
463 all_onsets.reserve(channels.size());
464
465 for (const auto& channel : channels) {
466 auto double_data = std::get<std::vector<double>>(channel);
467 std::span<const double> data_span(double_data.data(), double_data.size());
468
469 auto onset_sample_positions = Kinesis::Discrete::onset_positions(
470 data_span,
471 1024,
472 512,
473 threshold);
474
475 std::vector<double> onset_times;
476 onset_times.reserve(onset_sample_positions.size());
477 for (size_t sample_pos : onset_sample_positions) {
478 onset_times.push_back(static_cast<double>(sample_pos) / sample_rate);
479 }
480
481 all_onsets.push_back(onset_times);
482 }
483
484 return all_onsets;
485}
486
487//=========================================================================
488// BASIC TRANSFORMATIONS - Use MathematicalTransformer
489//=========================================================================
490
491void apply_gain(std::vector<double>& data, double gain_factor)
492{
493 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
494 transformer->set_parameter("gain_factor", gain_factor);
495
497 auto result = transformer->apply_operation(input);
498
499 data = std::get<std::vector<double>>(result.data[0]);
500}
501
502void apply_gain(Kakshya::DataVariant& data, double gain_factor)
503{
504 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
505 transformer->set_parameter("gain_factor", gain_factor);
506
508 auto result = transformer->apply_operation(input);
509
510 data = std::get<std::vector<double>>(result.data[0]);
511}
512
513void apply_gain_channels(std::vector<Kakshya::DataVariant>& channels, double gain_factor)
514{
515 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
516 transformer->set_parameter("gain_factor", gain_factor);
518 auto result = transformer->apply_operation(input);
519 channels = result.data;
520}
521
522void apply_gain_per_channel(std::vector<Kakshya::DataVariant>& channels, const std::vector<double>& gain_factors)
523{
524 if (gain_factors.size() != channels.size()) {
525 throw std::invalid_argument("Gain factors size must match channels size");
526 }
527
528 for (size_t i = 0; i < channels.size(); ++i) {
529 apply_gain(channels[i], gain_factors[i]);
530 }
531}
532
533std::vector<double> with_gain(const std::vector<double>& data, double gain_factor)
534{
535 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
536 transformer->set_parameter("gain_factor", gain_factor);
538 auto result = transformer->apply_operation(input);
539 return std::get<std::vector<double>>(result.data[0]);
540}
541
543{
544 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
545 transformer->set_parameter("gain_factor", gain_factor);
547 auto result = transformer->apply_operation(input);
548 return result.data[0];
549}
550
551std::vector<Kakshya::DataVariant> with_gain_channels(const std::vector<Kakshya::DataVariant>& channels, double gain_factor)
552{
553 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::GAIN);
554 transformer->set_parameter("gain_factor", gain_factor);
556 auto result = transformer->apply_operation(input);
557 return result.data;
558}
559
560void normalize(std::vector<double>& data, double target_peak)
561{
562 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::NORMALIZE);
563 transformer->set_parameter("target_peak", target_peak);
565 auto result = transformer->apply_operation(input);
566 data = std::get<std::vector<double>>(result.data[0]);
567}
568
569void normalize(Kakshya::DataVariant& data, double target_peak)
570{
571 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::NORMALIZE);
572 transformer->set_parameter("target_peak", target_peak);
574 auto result = transformer->apply_operation(input);
575 data = result.data[0];
576}
577
578void normalize_channels(std::vector<Kakshya::DataVariant>& channels, double target_peak)
579{
580 for (auto& channel : channels) {
581 normalize(channel, target_peak);
582 }
583}
584
585void normalize_together(std::vector<Kakshya::DataVariant>& channels, double target_peak)
586{
587 double global_peak = peak(channels);
588
589 if (global_peak > 0.0) {
590 double gain_factor = target_peak / global_peak;
591 apply_gain_channels(channels, gain_factor);
592 }
593}
594
595std::vector<double> normalized(const std::vector<double>& data, double target_peak)
596{
597 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::NORMALIZE);
598 transformer->set_parameter("target_peak", target_peak);
600 auto result = transformer->apply_operation(input);
601 return std::get<std::vector<double>>(result.data[0]);
602}
603
605{
606 auto transformer = std::make_shared<Yantra::MathematicalTransformer<>>(Yantra::MathematicalOperation::NORMALIZE);
607 transformer->set_parameter("target_peak", target_peak);
609 auto result = transformer->apply_operation(input);
610 return result.data[0];
611}
612
613std::vector<Kakshya::DataVariant> normalized_channels(const std::vector<Kakshya::DataVariant>& channels, double target_peak)
614{
615 std::vector<Kakshya::DataVariant> result;
616 result.reserve(channels.size());
617 for (const auto& channel : channels) {
618 result.push_back(normalized(channel, target_peak));
619 }
620 return result;
621}
622
623//=========================================================================
624// TEMPORAL TRANSFORMATIONS - Use TemporalTransformer
625//=========================================================================
626
627void reverse(std::vector<double>& data)
628{
629 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
631 auto result = transformer->apply_operation(input);
632 data = std::get<std::vector<double>>(result.data[0]);
633}
634
636{
637 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
639 auto result = transformer->apply_operation(input);
640 data = result.data[0];
641}
642
643void reverse_channels(std::vector<Kakshya::DataVariant>& channels)
644{
645 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
647 auto result = transformer->apply_operation(input);
648 channels = result.data;
649}
650
651std::vector<double> reversed(const std::vector<double>& data)
652{
653 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
655 auto result = transformer->apply_operation(input);
656 return std::get<std::vector<double>>(result.data[0]);
657}
658
660{
661 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
663 auto result = transformer->apply_operation(input);
664 return result.data[0];
665}
666
667std::vector<Kakshya::DataVariant> reversed_channels(const std::vector<Kakshya::DataVariant>& channels)
668{
669 auto transformer = std::make_shared<Yantra::TemporalTransformer<>>(Yantra::TemporalOperation::TIME_REVERSE);
671 auto result = transformer->apply_operation(input);
672 return result.data;
673}
674
675//=========================================================================
676// FREQUENCY DOMAIN - Use SpectralTransformer and EnergyAnalyzer
677//=========================================================================
678
679std::vector<double> magnitude_spectrum(const std::vector<double>& data, size_t window_size)
680{
681 auto energy_analyzer = std::make_shared<Yantra::EnergyAnalyzer<>>();
682 energy_analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
683 if (window_size > 0) {
684 energy_analyzer->set_window_parameters(window_size, window_size / 2);
685 }
686 auto result = energy_analyzer->analyze_energy({ Kakshya::DataVariant(data) });
687 return result.channels[0].energy_values;
688}
689
690std::vector<double> magnitude_spectrum(const Kakshya::DataVariant& data, size_t window_size)
691{
692 auto energy_analyzer = std::make_shared<Yantra::EnergyAnalyzer<>>();
693 energy_analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
694 if (window_size > 0) {
695 energy_analyzer->set_window_parameters(window_size, window_size / 2);
696 }
697 auto result = energy_analyzer->analyze_energy({ data });
698 return result.channels[0].energy_values;
699}
700
701std::vector<std::vector<double>> magnitude_spectrum_per_channel(const std::vector<Kakshya::DataVariant>& channels, size_t window_size)
702{
703 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
704 energy_analyzer->set_energy_method(Yantra::EnergyMethod::SPECTRAL);
705 if (window_size > 0) {
706 energy_analyzer->set_window_parameters(window_size, window_size / 2);
707 }
708 auto result = energy_analyzer->analyze_energy(channels);
709
710 std::vector<std::vector<double>> spectra;
711 for (const auto& channel : result.channels) {
712 spectra.push_back(channel.energy_values);
713 }
714 return spectra;
715}
716
717std::vector<double> power_spectrum(const std::vector<double>& data, size_t window_size)
718{
719 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
720 energy_analyzer->set_energy_method(Yantra::EnergyMethod::POWER);
721 if (window_size > 0) {
722 energy_analyzer->set_window_parameters(window_size, window_size / 2);
723 }
724 auto result = energy_analyzer->analyze_energy({ Kakshya::DataVariant(data) });
725 return result.channels[0].energy_values;
726}
727
728std::vector<double> power_spectrum(const Kakshya::DataVariant& data, size_t window_size)
729{
730 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
731 energy_analyzer->set_energy_method(Yantra::EnergyMethod::POWER);
732 if (window_size > 0) {
733 energy_analyzer->set_window_parameters(window_size, window_size / 2);
734 }
735 auto result = energy_analyzer->analyze_energy({ data });
736 return result.channels[0].energy_values;
737}
738
739std::vector<std::vector<double>> power_spectrum_per_channel(const std::vector<Kakshya::DataVariant>& channels, size_t window_size)
740{
741 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
742 energy_analyzer->set_energy_method(Yantra::EnergyMethod::POWER);
743 if (window_size > 0) {
744 energy_analyzer->set_window_parameters(window_size, window_size / 2);
745 }
746 auto result = energy_analyzer->analyze_energy(channels);
747
748 std::vector<std::vector<double>> spectra;
749 for (const auto& channel : result.channels) {
750 spectra.push_back(channel.energy_values);
751 }
752 return spectra;
753}
754
755//=========================================================================
756// PITCH AND TIME - Use EnergyAnalyzer for harmonic analysis
757//=========================================================================
758
759double estimate_pitch(const std::vector<double>& data, double sample_rate, double min_freq, double max_freq)
760{
761 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
762 energy_analyzer->set_energy_method(Yantra::EnergyMethod::HARMONIC);
763 energy_analyzer->set_parameter("sample_rate", sample_rate);
764 energy_analyzer->set_parameter("min_freq", min_freq);
765 energy_analyzer->set_parameter("max_freq", max_freq);
766 auto result = energy_analyzer->analyze_energy({ Kakshya::DataVariant(data) });
767
768 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy * sample_rate / 1000.0;
769}
770
771double estimate_pitch(const Kakshya::DataVariant& data, double sample_rate, double min_freq, double max_freq)
772{
773 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
774 energy_analyzer->set_energy_method(Yantra::EnergyMethod::HARMONIC);
775 energy_analyzer->set_parameter("sample_rate", sample_rate);
776 energy_analyzer->set_parameter("min_freq", min_freq);
777 energy_analyzer->set_parameter("max_freq", max_freq);
778 auto result = energy_analyzer->analyze_energy({ data });
779
780 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy * sample_rate / 1000.0;
781}
782
783std::vector<double> estimate_pitch_per_channel(const std::vector<Kakshya::DataVariant>& channels, double sample_rate, double min_freq, double max_freq)
784{
785 auto energy_analyzer = std::make_shared<Yantra::StandardEnergyAnalyzer>();
786 energy_analyzer->set_energy_method(Yantra::EnergyMethod::HARMONIC);
787 energy_analyzer->set_parameter("sample_rate", sample_rate);
788 energy_analyzer->set_parameter("min_freq", min_freq);
789 energy_analyzer->set_parameter("max_freq", max_freq);
790 auto result = energy_analyzer->analyze_energy(channels);
791
792 std::vector<double> pitches;
793 for (const auto& channel : result.channels) {
794 double pitch = channel.mean_energy * sample_rate / 1000.0;
795 pitches.push_back(pitch);
796 }
797 return pitches;
798}
799
800//=========================================================================
801// WINDOWING AND SEGMENTATION - Use FeatureExtractor and MathematicalTransformer
802//=========================================================================
803
804std::vector<double> extract_silent_data(const std::vector<double>& data,
805 double threshold,
806 size_t min_silence_duration)
807{
808 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
809 extractor->set_extraction_method(Yantra::ExtractionMethod::SILENCE_DATA);
810 extractor->set_parameter("silence_threshold", threshold);
811 extractor->set_parameter("min_duration", static_cast<uint32_t>(min_silence_duration));
812
814 auto result = extractor->apply_operation(input);
815
816 return result.data[0];
817}
818
819std::vector<double> extract_silent_data(const Kakshya::DataVariant& data,
820 double threshold,
821 size_t min_silence_duration)
822{
823 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
824 extractor->set_extraction_method(Yantra::ExtractionMethod::SILENCE_DATA);
825 extractor->set_parameter("silence_threshold", threshold);
826 extractor->set_parameter("min_duration", static_cast<uint32_t>(min_silence_duration));
827
829 auto result = extractor->apply_operation(input);
830
831 return result.data[0];
832}
833
834std::vector<double> extract_zero_crossing_regions(const std::vector<double>& data,
835 double threshold,
836 size_t region_size)
837{
838 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
839 extractor->set_extraction_method(Yantra::ExtractionMethod::ZERO_CROSSING_DATA);
840 extractor->set_parameter("threshold", threshold);
841 extractor->set_parameter("min_distance", 1.0);
842 extractor->set_parameter("region_size", static_cast<uint32_t>(region_size));
843
845 auto result = extractor->apply_operation(input);
846
847 return result.data[0];
848}
849
851 double threshold,
852 size_t region_size)
853{
854 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
855 extractor->set_extraction_method(Yantra::ExtractionMethod::ZERO_CROSSING_DATA);
856 extractor->set_parameter("threshold", threshold);
857 extractor->set_parameter("min_distance", 1.0);
858 extractor->set_parameter("region_size", static_cast<uint32_t>(region_size));
859
861 auto result = extractor->apply_operation(input);
862
863 return result.data[0];
864}
865
866void apply_window(std::vector<double>& data, const std::string& window_type)
867{
869
870 if (window_type == "hann" || window_type == "hanning") {
872 } else if (window_type == "hamming") {
874 } else if (window_type == "blackman") {
876 } else if (window_type == "rectangular" || window_type == "rect") {
878 } else {
880 }
881
882 auto window = Nodes::Generator::generate_window(data.size(), win_type);
883
884 for (size_t i = 0; i < data.size() && i < window.size(); ++i) {
885 data[i] *= window[i];
886 }
887}
888
889void apply_window(Kakshya::DataVariant& data, const std::string& window_type)
890{
891 auto double_data = std::get<std::vector<double>>(data);
892 apply_window(double_data, window_type);
893 data = Kakshya::DataVariant(double_data);
894}
895
896void apply_window_channels(std::vector<Kakshya::DataVariant>& channels, const std::string& window_type)
897{
898 for (auto& channel : channels) {
899 apply_window(channel, window_type);
900 }
901}
902
903std::vector<std::vector<double>> windowed_segments(const std::vector<double>& data,
904 size_t window_size,
905 size_t hop_size)
906{
907 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>(static_cast<uint32_t>(window_size), static_cast<uint32_t>(hop_size),
909 extractor->set_parameter("overlap", double(hop_size) / window_size);
910
912 auto result = extractor->apply_operation(input);
913
914 auto extracted_data = result.data[0];
915
916 std::vector<std::vector<double>> segments;
917 for (size_t i = 0; i < extracted_data.size(); i += window_size) {
918 size_t end_idx = std::min(i + window_size, extracted_data.size());
919 segments.emplace_back(extracted_data.begin() + i, extracted_data.begin() + end_idx);
920 }
921
922 return segments;
923}
924
925std::vector<std::vector<double>> windowed_segments(const Kakshya::DataVariant& data,
926 size_t window_size,
927 size_t hop_size)
928{
929 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>(static_cast<uint32_t>(window_size), static_cast<uint32_t>(hop_size),
931 extractor->set_parameter("overlap", double(hop_size) / window_size);
932
934 auto result = extractor->apply_operation(input);
935
936 auto extracted_data = result.data[0];
937
938 std::vector<std::vector<double>> segments;
939 for (size_t i = 0; i < extracted_data.size(); i += window_size) {
940 size_t end_idx = std::min(i + window_size, extracted_data.size());
941 segments.emplace_back(extracted_data.begin() + i, extracted_data.begin() + end_idx);
942 }
943
944 return segments;
945}
946
947std::vector<std::vector<std::vector<double>>> windowed_segments_per_channel(const std::vector<Kakshya::DataVariant>& channels,
948 size_t window_size,
949 size_t hop_size)
950{
951 std::vector<std::vector<std::vector<double>>> all_segments;
952 all_segments.reserve(channels.size());
953
954 for (const auto& channel : channels) {
955 all_segments.push_back(windowed_segments(channel, window_size, hop_size));
956 }
957
958 return all_segments;
959}
960
961std::vector<std::pair<size_t, size_t>> detect_silence(const std::vector<double>& data,
962 double threshold,
963 size_t min_silence_duration)
964{
965 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
966 extractor->set_extraction_method(Yantra::ExtractionMethod::SILENCE_DATA);
967 extractor->set_parameter("silence_threshold", threshold);
968 extractor->set_parameter("min_duration", static_cast<uint32_t>(min_silence_duration));
969
971 auto result = extractor->apply_operation(input);
972
973 std::vector<std::pair<size_t, size_t>> silence_regions;
974 auto window_positions_opt = result.template get_metadata<std::vector<std::pair<size_t, size_t>>>("window_positions");
975 if (window_positions_opt.has_value()) {
976 silence_regions = window_positions_opt.value();
977 }
978
979 return silence_regions;
980}
981
982std::vector<std::pair<size_t, size_t>> detect_silence(const Kakshya::DataVariant& data,
983 double threshold,
984 size_t min_silence_duration)
985{
986 auto extractor = std::make_shared<Yantra::FeatureExtractor<>>();
987 extractor->set_extraction_method(Yantra::ExtractionMethod::SILENCE_DATA);
988 extractor->set_parameter("silence_threshold", threshold);
989 extractor->set_parameter("min_duration", static_cast<uint32_t>(min_silence_duration));
990
992 auto result = extractor->apply_operation(input);
993
994 std::vector<std::pair<size_t, size_t>> silence_regions;
995 auto window_positions_opt = result.template get_metadata<std::vector<std::pair<size_t, size_t>>>("window_positions");
996 if (window_positions_opt.has_value()) {
997 silence_regions = window_positions_opt.value();
998 }
999
1000 return silence_regions;
1001}
1002
1003std::vector<std::vector<std::pair<size_t, size_t>>> detect_silence_per_channel(const std::vector<Kakshya::DataVariant>& channels,
1004 double threshold,
1005 size_t min_silence_duration)
1006{
1007 std::vector<std::vector<std::pair<size_t, size_t>>> all_silence_regions;
1008 all_silence_regions.reserve(channels.size());
1009
1010 for (const auto& channel : channels) {
1011 all_silence_regions.push_back(detect_silence(channel, threshold, min_silence_duration));
1012 }
1013
1014 return all_silence_regions;
1015}
1016
1017//=========================================================================
1018// UTILITY AND CONVERSION - Use MathematicalTransformer for mixing
1019//=========================================================================
1020
1021std::vector<double> mix(const std::vector<std::vector<double>>& streams)
1022{
1023 if (streams.empty())
1024 return {};
1025
1026 size_t max_length = 0;
1027 for (const auto& stream : streams) {
1028 max_length = std::max(max_length, stream.size());
1029 }
1030
1031 std::vector<double> result(max_length, 0.0);
1032
1033 for (const auto& stream : streams) {
1034 for (size_t i = 0; i < stream.size(); ++i) {
1035 result[i] += stream[i];
1036 }
1037 }
1038
1039 double gain = 1.0 / static_cast<double>(streams.size());
1040 apply_gain(result, gain);
1041
1042 return result;
1043}
1044
1045std::vector<double> mix(const std::vector<Kakshya::DataVariant>& streams)
1046{
1047 if (streams.empty())
1048 return {};
1049
1050 auto numeric_data = Yantra::OperationHelper::extract_numeric_data(streams);
1051
1052 if (is_same_size(numeric_data)) {
1053 size_t channel_length = numeric_data[0].size();
1054 std::vector<double> result(channel_length, 0.0);
1055
1056 for (const auto& span : numeric_data) {
1057 for (size_t i = 0; i < span.size(); ++i) {
1058 result[i] += span[i];
1059 }
1060 }
1061
1062 double gain = 1.0 / static_cast<double>(numeric_data.size());
1063 apply_gain(result, gain);
1064
1065 return result;
1066 } else {
1067 std::vector<std::vector<double>> double_streams;
1068 double_streams.reserve(streams.size());
1069
1070 for (const auto& span : numeric_data) {
1071 double_streams.emplace_back(span.begin(), span.end());
1072 }
1073
1074 return mix(double_streams);
1075 }
1076}
1077
1078std::vector<double> mix_with_gains(const std::vector<std::vector<double>>& streams,
1079 const std::vector<double>& gains)
1080{
1081 if (streams.empty() || gains.size() != streams.size()) {
1082 throw std::invalid_argument("Streams and gains vectors must have the same size");
1083 }
1084
1085 size_t max_length = 0;
1086 for (const auto& stream : streams) {
1087 max_length = std::max(max_length, stream.size());
1088 }
1089
1090 std::vector<double> result(max_length, 0.0);
1091
1092 for (size_t s = 0; s < streams.size(); ++s) {
1093 const auto& stream = streams[s];
1094 double gain = gains[s];
1095
1096 for (size_t i = 0; i < stream.size(); ++i) {
1097 result[i] += stream[i] * gain;
1098 }
1099 }
1100
1101 return result;
1102}
1103
1104std::vector<double> mix_with_gains(const std::vector<Kakshya::DataVariant>& streams,
1105 const std::vector<double>& gains)
1106{
1107 if (streams.empty() || gains.size() != streams.size()) {
1108 throw std::invalid_argument("Streams and gains vectors must have the same size");
1109 }
1110
1111 auto numeric_data = Yantra::OperationHelper::extract_numeric_data(streams);
1112
1113 if (is_same_size(numeric_data)) {
1114 size_t channel_length = numeric_data[0].size();
1115 std::vector<double> result(channel_length, 0.0);
1116
1117 for (size_t s = 0; s < numeric_data.size(); ++s) {
1118 const auto& span = numeric_data[s];
1119 double gain = gains[s];
1120
1121 for (size_t i = 0; i < span.size(); ++i) {
1122 result[i] += span[i] * gain;
1123 }
1124 }
1125
1126 return result;
1127 }
1128
1129 std::vector<std::vector<double>> double_streams;
1130 double_streams.reserve(streams.size());
1131
1132 for (const auto& span : numeric_data) {
1133 double_streams.emplace_back(span.begin(), span.end());
1134 }
1135
1136 return mix_with_gains(double_streams, gains);
1137}
1138
1139std::vector<double> to_double_vector(const Kakshya::DataVariant& data)
1140{
1142 return span.empty() ? std::vector<double> {} : std::vector<double>(span.begin(), span.end());
1143}
1144
1145Kakshya::DataVariant to_data_variant(const std::vector<double>& data)
1146{
1147 return { data };
1148}
1149
1150std::vector<std::vector<double>> to_double_vectors(const std::vector<Kakshya::DataVariant>& channels)
1151{
1152 auto spans = Yantra::OperationHelper::extract_numeric_data(channels);
1153 std::vector<std::vector<double>> result;
1154 result.reserve(spans.size());
1155
1156 for (const auto& span : spans) {
1157 result.emplace_back(span.begin(), span.end());
1158 }
1159
1160 return result;
1161}
1162
1163std::vector<Kakshya::DataVariant> to_data_variants(const std::vector<std::vector<double>>& channel_data)
1164{
1165 std::vector<Kakshya::DataVariant> result;
1166 result.reserve(channel_data.size());
1167
1168 for (const auto& channel : channel_data) {
1169 result.emplace_back(channel);
1170 }
1171
1172 return result;
1173}
1174
1175//=========================================================================
1176// INITIALIZATION
1177//=========================================================================
1178
1180{
1181 // Initialize any global Yantra state if needed
1182 // Operations are generally stateless, so minimal initialization required
1183}
1184
1185} // namespace MayaFlux
Discrete sequence analysis primitives for MayaFlux::Kinesis.
Span-based energy analysis for digital signals in Maya Flux.
Concrete feature extractor using analyzer-guided extraction.
Data analysis and transformation convenience API.
static std::span< double > extract_numeric_data(const T &compute_data)
extract numeric data from single-variant types
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:73
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< double > generate_window(uint32_t size, WindowType window_type)
Generate window coefficients using C++20 ranges.
@ SPECTRAL
Spectral energy (FFT-based)
@ DYNAMIC_RANGE
Dynamic range (dB)
@ ZERO_CROSSING
Zero-crossing rate.
@ HARMONIC
Harmonic energy (low-frequency content)
@ POWER
Power (sum of squares)
@ GAIN
Linear gain/attenuation.
@ SILENCE_DATA
Extract actual silent regions.
@ ZERO_CROSSING_DATA
Extract actual data at zero crossing points.
@ OVERLAPPING_WINDOWS
Extract overlapping windowed data.
@ TIME_REVERSE
Reverse temporal order.
std::vector< std::vector< double > > to_double_vectors(const std::vector< Kakshya::DataVariant > &channels)
Convert multi-channel data to vector of double vectors.
Definition Yantra.cpp:1150
std::vector< size_t > zero_crossings(const std::vector< double > &data, double threshold)
Detect zero crossings in single-channel signal.
Definition Yantra.cpp:268
Kakshya::DataVariant to_data_variant(const std::vector< double > &data)
Convert vector<double> to DataVariant.
Definition Yantra.cpp:1145
std::vector< double > zero_crossing_rate_per_channel(const std::vector< Kakshya::DataVariant > &channels, size_t window_size)
Calculate zero crossing rate per channel for multi-channel data.
Definition Yantra.cpp:373
std::vector< Kakshya::DataVariant > with_gain_channels(const std::vector< Kakshya::DataVariant > &channels, double gain_factor)
Apply gain to multi-channel data (non-destructive)
Definition Yantra.cpp:551
std::vector< double > dynamic_range_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate dynamic range per channel for multi-channel data.
Definition Yantra.cpp:184
double std_dev_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate standard deviation across all channels (mix then analyze)
Definition Yantra.cpp:156
std::vector< std::vector< double > > magnitude_spectrum_per_channel(const std::vector< Kakshya::DataVariant > &channels, size_t window_size)
Compute magnitude spectrum per channel for multi-channel data.
Definition Yantra.cpp:701
std::vector< double > estimate_pitch_per_channel(const std::vector< Kakshya::DataVariant > &channels, double sample_rate, double min_freq, double max_freq)
Estimate fundamental frequency per channel for multi-channel data.
Definition Yantra.cpp:783
double estimate_pitch(const std::vector< double > &data, double sample_rate, double min_freq, double max_freq)
Estimate fundamental frequency using autocorrelation for single-channel data.
Definition Yantra.cpp:759
std::vector< Kakshya::DataVariant > reversed_channels(const std::vector< Kakshya::DataVariant > &channels)
Reverse time order of multi-channel data (non-destructive)
Definition Yantra.cpp:667
std::vector< double > peak_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Find peak amplitude per channel for multi-channel data.
Definition Yantra.cpp:244
double zero_crossing_rate(const std::vector< double > &data, size_t window_size)
Calculate zero crossing rate for single-channel data.
Definition Yantra.cpp:351
void reverse(std::vector< double > &data)
Reverse time order of single-channel data (in-place)
Definition Yantra.cpp:627
std::vector< double > mean_per_channel(const std::vector< Kakshya::DataVariant > &data)
Calculate mean per channel for multi-channel data.
Definition Yantra.cpp:57
void apply_gain_channels(std::vector< Kakshya::DataVariant > &channels, double gain_factor)
Apply gain to multi-channel data (in-place)
Definition Yantra.cpp:513
void normalize_together(std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize multi-channel data relative to global peak (in-place)
Definition Yantra.cpp:585
std::vector< double > to_double_vector(const Kakshya::DataVariant &data)
Convert DataVariant to vector<double> if possible.
Definition Yantra.cpp:1139
std::vector< std::vector< std::vector< double > > > windowed_segments_per_channel(const std::vector< Kakshya::DataVariant > &channels, size_t window_size, size_t hop_size)
Split multi-channel data into overlapping windows per channel.
Definition Yantra.cpp:947
std::vector< double > with_gain(const std::vector< double > &data, double gain_factor)
Apply gain to single-channel data (non-destructive)
Definition Yantra.cpp:533
double dynamic_range(const std::vector< double > &data)
Calculate dynamic range (max/min ratio in dB) of single-channel data.
Definition Yantra.cpp:168
std::vector< std::pair< size_t, size_t > > detect_silence(const std::vector< double > &data, double threshold, size_t min_silence_duration)
Detect silence regions in single-channel data.
Definition Yantra.cpp:961
double rms(const std::vector< double > &data)
Calculate RMS (Root Mean Square) energy of single-channel data.
Definition Yantra.cpp:84
void normalize_channels(std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize each channel independently to specified peak level (in-place)
Definition Yantra.cpp:578
void reverse_channels(std::vector< Kakshya::DataVariant > &channels)
Reverse time order of multi-channel data (in-place)
Definition Yantra.cpp:643
double peak_channel(const std::vector< Kakshya::DataVariant > &channels, size_t channel_index)
Find peak amplitude in specific channel.
Definition Yantra.cpp:256
std::vector< double > extract_zero_crossing_regions(const std::vector< double > &data, double threshold, size_t region_size)
Extract zero crossing regions from single-channel data.
Definition Yantra.cpp:834
std::vector< double > std_dev_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate standard deviation per channel for multi-channel data.
Definition Yantra.cpp:144
std::vector< double > reversed(const std::vector< double > &data)
Reverse time order of single-channel data (non-destructive)
Definition Yantra.cpp:651
std::vector< std::vector< double > > power_spectrum_per_channel(const std::vector< Kakshya::DataVariant > &channels, size_t window_size)
Compute power spectrum per channel for multi-channel data.
Definition Yantra.cpp:739
std::vector< Kakshya::DataVariant > to_data_variants(const std::vector< std::vector< double > > &channel_data)
Convert vector of double vectors to multi-channel DataVariant format.
Definition Yantra.cpp:1163
std::vector< double > extract_silent_data(const std::vector< double > &data, double threshold, size_t min_silence_duration)
Extract silent regions from single-channel data.
Definition Yantra.cpp:804
double dynamic_range_global(const std::vector< Kakshya::DataVariant > &channels)
Calculate dynamic range across all channels (global min/max)
Definition Yantra.cpp:196
static bool is_same_size(const std::vector< std::span< double > > &data)
Definition Yantra.cpp:14
std::vector< double > magnitude_spectrum(const std::vector< double > &data, size_t window_size)
Compute magnitude spectrum for single-channel data.
Definition Yantra.cpp:679
void apply_window_channels(std::vector< Kakshya::DataVariant > &channels, const std::string &window_type)
Apply window function to multi-channel data (in-place)
Definition Yantra.cpp:896
std::vector< std::vector< double > > detect_onsets_per_channel(const std::vector< Kakshya::DataVariant > &channels, double sample_rate, double threshold)
Detect onset times per channel for multi-channel signal.
Definition Yantra.cpp:460
void normalize(std::vector< double > &data, double target_peak)
Normalize single-channel data to specified peak level (in-place)
Definition Yantra.cpp:560
void apply_window(std::vector< double > &data, const std::string &window_type)
Apply window function to single-channel data (in-place)
Definition Yantra.cpp:866
double rms_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate RMS energy across all channels (mix then analyze)
Definition Yantra.cpp:112
std::vector< std::vector< double > > windowed_segments(const std::vector< double > &data, size_t window_size, size_t hop_size)
Split single-channel data into overlapping windows.
Definition Yantra.cpp:903
std::vector< double > mix_with_gains(const std::vector< std::vector< double > > &streams, const std::vector< double > &gains)
Mix multiple data streams with specified gains.
Definition Yantra.cpp:1078
std::vector< Kakshya::DataVariant > normalized_channels(const std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize each channel independently (non-destructive)
Definition Yantra.cpp:613
std::vector< double > spectral_centroid_per_channel(const std::vector< Kakshya::DataVariant > &channels, double sample_rate)
Find spectral centroid per channel for multi-channel data.
Definition Yantra.cpp:407
static std::vector< double > concat_vectors(const std::vector< std::span< double > > &data)
Definition Yantra.cpp:24
double spectral_centroid(const std::vector< double > &data, double sample_rate)
Find spectral centroid (brightness measure) for single-channel data.
Definition Yantra.cpp:389
void initialize_yantra()
Initialize Yantra subsystem with default configuration.
Definition Yantra.cpp:1179
double std_dev(const std::vector< double > &data)
Calculate standard deviation of single-channel data.
Definition Yantra.cpp:128
std::vector< double > normalized(const std::vector< double > &data, double target_peak)
Normalize single-channel data (non-destructive)
Definition Yantra.cpp:595
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.
Definition Yantra.cpp:41
double mean_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate mean across all channels (mix then analyze)
Definition Yantra.cpp:72
std::vector< double > detect_onsets(const std::vector< double > &data, double sample_rate, double threshold)
Detect onset times in single-channel signal.
Definition Yantra.cpp:421
std::vector< std::vector< size_t > > zero_crossings_per_channel(const std::vector< Kakshya::DataVariant > &channels, double threshold)
Detect zero crossings per channel for multi-channel signal.
Definition Yantra.cpp:321
double peak(const std::vector< double > &data)
Find peak amplitude in single-channel data.
Definition Yantra.cpp:216
void apply_gain(std::vector< double > &data, double gain_factor)
Apply gain to single-channel data (in-place)
Definition Yantra.cpp:491
void apply_gain_per_channel(std::vector< Kakshya::DataVariant > &channels, const std::vector< double > &gain_factors)
Apply different gain to each channel (in-place)
Definition Yantra.cpp:522
std::vector< double > mix(const std::vector< std::vector< double > > &streams)
Mix multiple data streams with equal weighting.
Definition Yantra.cpp:1021
std::vector< double > rms_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate RMS energy per channel for multi-channel data.
Definition Yantra.cpp:100
std::vector< std::vector< std::pair< size_t, size_t > > > detect_silence_per_channel(const std::vector< Kakshya::DataVariant > &channels, double threshold, size_t min_silence_duration)
Detect silence regions per channel for multi-channel data.
Definition Yantra.cpp:1003
std::vector< double > power_spectrum(const std::vector< double > &data, size_t window_size)
Compute power spectrum for single-channel data.
Definition Yantra.cpp:717
Main namespace for the Maya Flux audio engine.
Definition LiveAid.hpp:6
T data
The actual computation data.
Definition DataIO.hpp:25
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:24