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