13namespace D = Kinesis::Discrete;
16 bool is_same_size(
const std::vector<std::span<double>>& data)
21 const auto expected_size = data.front().size();
22 return std::ranges::all_of(data,
23 [&expected_size](
const auto& v) {
return v.size() == expected_size; });
26 std::vector<double> concat_vectors(
const std::vector<std::span<double>>& data)
28 std::vector<double> result;
29 result.reserve(std::accumulate(
30 data.begin(), data.end(),
size_t(0),
31 [](
size_t sum,
const auto& span) { return sum + span.size(); }));
33 for (
const auto& span : data) {
34 result.insert(result.end(), span.begin(), span.end());
39 std::span<double> as_span(std::vector<double>& v)
noexcept
41 return { v.data(), v.size() };
44 std::span<double> as_span(Kakshya::DataVariant& v)
46 return Yantra::OperationHelper::extract_numeric_data(v);
55double mean(
const std::vector<double>& data)
57 static const auto s_op = [] {
58 auto a = std::make_shared<Yantra::StatisticalAnalyzer<>>();
67 static const auto s_op = [] {
68 auto a = std::make_shared<Yantra::StatisticalAnalyzer<>>();
72 return s_op->analyze_statistics({ data }).channel_statistics[0].mean_stat;
77 static const auto s_op = [] {
78 auto a = std::make_shared<Yantra::StatisticalAnalyzer<>>();
82 auto result = s_op->analyze_statistics(channels);
84 std::vector<double> means;
85 means.reserve(result.channel_statistics.size());
86 for (
const auto& stats : result.channel_statistics)
87 means.push_back(stats.mean_stat);
94 if (is_same_size(data)) {
96 return std::accumulate(result.begin(), result.end(), 0.0) / (double)result.size();
98 auto mixed = concat_vectors(data);
102double rms(
const std::vector<double>& data)
104 static const auto s_op = [] {
105 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
110 return result.channel_statistics[0].statistical_values.empty() ? 0.0 : result.channel_statistics[0].statistical_values[0];
115 static const auto s_op = [] {
116 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
120 auto result = s_op->analyze_statistics({ data });
121 return result.channel_statistics[0].statistical_values.empty() ? 0.0 : result.channel_statistics[0].statistical_values[0];
126 static const auto s_op = [] {
127 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
131 auto result = s_op->analyze_statistics(channels);
132 std::vector<double> rms_values;
133 rms_values.reserve(result.channel_statistics.size());
135 for (
const auto& stats : result.channel_statistics) {
136 rms_values.push_back(stats.statistical_values.empty() ? 0.0 : stats.statistical_values[0]);
145 if (is_same_size(data)) {
147 double sum_squares = 0.0;
148 for (
double v : result)
149 sum_squares += v * v;
150 return std::sqrt(sum_squares / (
double)result.size());
152 auto mixed = concat_vectors(data);
156double std_dev(
const std::vector<double>& data)
158 static const auto s_op = [] {
159 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
163 return s_op->analyze_statistics({
Kakshya::DataVariant(data) }).channel_statistics[0].stat_std_dev;
168 static const auto s_op = [] {
169 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
173 return s_op->analyze_statistics({ data }).channel_statistics[0].stat_std_dev;
178 static const auto s_op = [] {
179 auto a = std::make_shared<Yantra::StandardStatisticalAnalyzer>();
183 auto result = s_op->analyze_statistics(channels);
184 std::vector<double> std_devs;
186 std_devs.reserve(result.channel_statistics.size());
187 for (
const auto& stats : result.channel_statistics) {
188 std_devs.push_back(stats.stat_std_dev);
197 if (is_same_size(data)) {
199 return std::accumulate(result.begin(), result.end(), 0.0) / (double)result.size();
201 auto mixed = concat_vectors(data);
211 static const auto s_op = [] {
212 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
217 return result.channels.empty() || result.channels[0].energy_values.empty() ? 0.0 : result.channels[0].energy_values[0];
222 static const auto s_op = [] {
223 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
227 auto result = s_op->analyze_energy({ data });
228 return result.channels.empty() || result.channels[0].energy_values.empty() ? 0.0 : result.channels[0].energy_values[0];
233 static const auto s_op = [] {
234 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
238 auto result = s_op->analyze_energy(channels);
239 std::vector<double>
ranges;
241 ranges.reserve(result.channels.size());
242 for (
const auto& ch : result.channels) {
243 ranges.push_back(ch.energy_values.empty() ? 0.0 : ch.energy_values[0]);
252 double global_min = std::numeric_limits<double>::max();
253 double global_max = std::numeric_limits<double>::lowest();
255 for (
const auto& span : data) {
256 auto [min_it, max_it] = std::ranges::minmax_element(span);
257 if (min_it != span.end()) {
258 global_min = std::min(global_min, *min_it);
259 global_max = std::max(global_max, *max_it);
263 if (global_min <= 0.0 || global_max <= 0.0)
265 return 20.0 * std::log10(global_max / std::abs(global_min));
268double peak(
const std::vector<double>& data)
270 static const auto s_op = [] {
271 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
276 return result.channels.empty() ? 0.0 : result.channels[0].max_energy;
281 static const auto s_op = [] {
282 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
286 auto result = s_op->analyze_energy({ data });
287 return result.channels.empty() ? 0.0 : result.channels[0].max_energy;
290double peak(
const std::vector<Kakshya::DataVariant>& channels)
292 static const auto s_op = [] {
293 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
297 auto result = s_op->analyze_energy(channels);
298 double global_peak = 0.0;
299 for (
const auto& ch : result.channels)
300 global_peak = std::max(global_peak, ch.max_energy);
306 static const auto s_op = [] {
307 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
311 auto result = s_op->analyze_energy(channels);
312 std::vector<double> peaks;
313 peaks.reserve(result.channels.size());
315 for (
const auto& ch : result.channels)
316 peaks.push_back(ch.max_energy);
320double peak_channel(
const std::vector<Kakshya::DataVariant>& channels,
size_t channel_index)
322 if (channel_index >= channels.size()) {
324 "Channel index out of range");
326 return peak(channels[channel_index]);
333std::vector<size_t>
zero_crossings(
const std::vector<double>& data,
double threshold)
335 static const auto s_op = [] {
336 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
341 if (result.channels.empty())
344 const auto& positions = result.channels[0].event_positions;
345 if (threshold <= 0.0)
348 std::vector<size_t> filtered;
349 for (
size_t pos : positions) {
350 if (pos < data.size() && std::abs(data[pos]) >= threshold)
351 filtered.push_back(pos);
358 static const auto s_op = [] {
359 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
363 auto result = s_op->analyze_energy({ data });
364 if (result.channels.empty())
367 const auto& positions = result.channels[0].event_positions;
368 if (threshold <= 0.0)
371 auto double_data = std::get<std::vector<double>>(data);
372 std::vector<size_t> filtered;
373 for (
size_t pos : positions) {
374 if (pos < double_data.size() && std::abs(double_data[pos]) >= threshold)
375 filtered.push_back(pos);
382 static const auto s_op = [] {
383 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
387 auto result = s_op->analyze_energy(channels);
388 std::vector<std::vector<size_t>> all_crossings;
389 all_crossings.reserve(result.channels.size());
391 for (
size_t ch = 0; ch < result.channels.size(); ++ch) {
392 const auto& positions = result.channels[ch].event_positions;
393 if (threshold <= 0.0) {
394 all_crossings.push_back(positions);
397 auto double_data = std::get<std::vector<double>>(channels[ch]);
398 std::vector<size_t> filtered;
399 for (
size_t pos : positions) {
400 if (pos < double_data.size() && std::abs(double_data[pos]) >= threshold)
401 filtered.push_back(pos);
403 all_crossings.push_back(filtered);
405 return all_crossings;
410 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
413 a->set_window_parameters(window_size, window_size / 2);
415 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
420 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
423 a->set_window_parameters(window_size, window_size / 2);
424 auto result =
a->analyze_energy({ data });
425 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
430 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
433 a->set_window_parameters(window_size, window_size / 2);
434 auto result =
a->analyze_energy(channels);
435 std::vector<double> rates;
437 rates.reserve(result.channels.size());
438 for (
const auto& ch : result.channels)
439 rates.push_back(ch.mean_energy);
445 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
447 a->set_parameter(
"sample_rate", sample_rate);
449 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
454 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
456 a->set_parameter(
"sample_rate", sample_rate);
457 auto result =
a->analyze_energy({ data });
458 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy;
463 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
465 a->set_parameter(
"sample_rate", sample_rate);
466 auto result =
a->analyze_energy(channels);
467 std::vector<double> centroids;
469 centroids.reserve(result.channels.size());
470 for (
const auto& ch : result.channels)
471 centroids.push_back(ch.mean_energy);
476std::vector<double>
detect_onsets(
const std::vector<double>& data,
double sample_rate,
double threshold)
479 std::span<const double>(data.data(), data.size()), 1024, 512, threshold);
480 std::vector<double>
times;
482 times.reserve(onset_positions.size());
483 for (
size_t pos : onset_positions) {
484 times.push_back(
static_cast<double>(pos) / sample_rate);
491 auto double_data = std::get<std::vector<double>>(data);
493 std::span<const double>(double_data.data(), double_data.size()), 1024, 512, threshold);
495 std::vector<double>
times;
497 times.reserve(onset_positions.size());
498 for (
size_t pos : onset_positions)
499 times.push_back(
static_cast<double>(pos) / sample_rate);
503std::vector<std::vector<double>>
detect_onsets_per_channel(
const std::vector<Kakshya::DataVariant>& channels,
double sample_rate,
double threshold)
505 std::vector<std::vector<double>> all_onsets;
506 all_onsets.reserve(channels.size());
508 for (
const auto&
channel : channels)
517void apply_gain(std::vector<double>& data,
double gain_factor)
519 D::linear(as_span(data), gain_factor, 0.0);
524 D::linear(as_span(data), gain_factor, 0.0);
529 for (
auto& ch : channels)
535 if (gain_factors.size() != channels.size()) {
537 "Gain factors size must match channels size");
539 for (
size_t i = 0; i < channels.size(); ++i)
543std::vector<double>
with_gain(
const std::vector<double>& data,
double gain_factor)
546 D::linear(as_span(out), gain_factor, 0.0);
553 D::linear(as_span(out), gain_factor, 0.0);
557std::vector<Kakshya::DataVariant>
with_gain_channels(
const std::vector<Kakshya::DataVariant>& channels,
double gain_factor)
561 D::linear(as_span(ch), gain_factor, 0.0);
565void normalize(std::vector<double>& data,
double target_peak)
577 for (
auto& ch : channels)
583 const double global_peak =
peak(channels);
584 if (global_peak > 0.0)
588std::vector<double>
normalized(
const std::vector<double>& data,
double target_peak)
602std::vector<Kakshya::DataVariant>
normalized_channels(
const std::vector<Kakshya::DataVariant>& channels,
double target_peak)
626 for (
auto& ch : channels)
630std::vector<double>
reversed(
const std::vector<double>& data)
644std::vector<Kakshya::DataVariant>
reversed_channels(
const std::vector<Kakshya::DataVariant>& channels)
658 auto a = std::make_shared<Yantra::EnergyAnalyzer<>>();
661 a->set_window_parameters(window_size, window_size / 2);
667 auto a = std::make_shared<Yantra::EnergyAnalyzer<>>();
670 a->set_window_parameters(window_size, window_size / 2);
671 return a->analyze_energy({ data }).channels[0].energy_values;
676 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
679 a->set_window_parameters(window_size, window_size / 2);
680 auto result =
a->analyze_energy(channels);
681 std::vector<std::vector<double>> spectra;
683 spectra.reserve(result.channels.size());
684 for (
const auto& ch : result.channels) {
685 spectra.push_back(ch.energy_values);
690std::vector<double>
power_spectrum(
const std::vector<double>& data,
size_t window_size)
692 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
695 a->set_window_parameters(window_size, window_size / 2);
701 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
704 a->set_window_parameters(window_size, window_size / 2);
705 return a->analyze_energy({ data }).channels[0].energy_values;
710 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
713 a->set_window_parameters(window_size, window_size / 2);
714 auto result =
a->analyze_energy(channels);
715 std::vector<std::vector<double>> spectra;
717 spectra.reserve(result.channels.size());
718 for (
const auto& ch : result.channels) {
719 spectra.push_back(ch.energy_values);
729double estimate_pitch(
const std::vector<double>& data,
double sample_rate,
double min_freq,
double max_freq)
731 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
733 a->set_parameter(
"sample_rate", sample_rate);
734 a->set_parameter(
"min_freq", min_freq);
735 a->set_parameter(
"max_freq", max_freq);
737 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy * sample_rate / 1000.0;
742 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
744 a->set_parameter(
"sample_rate", sample_rate);
745 a->set_parameter(
"min_freq", min_freq);
746 a->set_parameter(
"max_freq", max_freq);
747 auto result =
a->analyze_energy({ data });
748 return result.channels.empty() ? 0.0 : result.channels[0].mean_energy * sample_rate / 1000.0;
751std::vector<double>
estimate_pitch_per_channel(
const std::vector<Kakshya::DataVariant>& channels,
double sample_rate,
double min_freq,
double max_freq)
753 auto a = std::make_shared<Yantra::StandardEnergyAnalyzer>();
755 a->set_parameter(
"sample_rate", sample_rate);
756 a->set_parameter(
"min_freq", min_freq);
757 a->set_parameter(
"max_freq", max_freq);
758 auto result =
a->analyze_energy(channels);
759 std::vector<double> pitches;
760 pitches.reserve(result.channels.size());
762 for (
const auto& ch : result.channels) {
763 pitches.push_back(ch.mean_energy * sample_rate / 1000.0);
772std::vector<double>
extract_silent_data(
const std::vector<double>& data,
double threshold,
size_t min_silence_duration)
774 static const auto s_op = [] {
775 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
779 s_op->set_parameter(
"silence_threshold", threshold);
780 s_op->set_parameter(
"min_duration",
static_cast<uint32_t
>(min_silence_duration));
782 return s_op->apply_operation(input).
data[0];
787 static const auto s_op = [] {
788 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
792 s_op->set_parameter(
"silence_threshold", threshold);
793 s_op->set_parameter(
"min_duration",
static_cast<uint32_t
>(min_silence_duration));
795 return s_op->apply_operation(input).
data[0];
800 static const auto s_op = [] {
801 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
803 e->set_parameter(
"min_distance", 1.0);
806 s_op->set_parameter(
"threshold", threshold);
807 s_op->set_parameter(
"region_size",
static_cast<uint32_t
>(region_size));
809 return s_op->apply_operation(input).
data[0];
814 static const auto s_op = [] {
815 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
817 e->set_parameter(
"min_distance", 1.0);
820 s_op->set_parameter(
"threshold", threshold);
821 s_op->set_parameter(
"region_size",
static_cast<uint32_t
>(region_size));
823 return s_op->apply_operation(input).
data[0];
826void apply_window(std::vector<double>& data,
const std::string& window_type)
830 if (window_type ==
"hann" || window_type ==
"hanning") {
832 }
else if (window_type ==
"hamming") {
834 }
else if (window_type ==
"blackman") {
836 }
else if (window_type ==
"rectangular" || window_type ==
"rect") {
843 for (
size_t i = 0; i < data.size() && i < window.size(); ++i)
844 data[i] *= window[i];
849 auto double_data = std::get<std::vector<double>>(data);
856 for (
auto& ch : channels)
860std::vector<std::vector<double>>
windowed_segments(
const std::vector<double>& data,
size_t window_size,
size_t hop_size)
862 auto e = std::make_shared<Yantra::FeatureExtractor<>>(
863 static_cast<uint32_t
>(window_size),
static_cast<uint32_t
>(hop_size),
865 e->set_parameter(
"overlap",
double(hop_size) / (double)window_size);
868 auto extracted = e->apply_operation(input).
data[0];
869 std::vector<std::vector<double>> segments;
870 for (
size_t i = 0; i < extracted.size(); i += window_size) {
871 size_t end = std::min(i + window_size, extracted.size());
872 segments.emplace_back(extracted.begin() + i, extracted.begin() + end);
879 auto e = std::make_shared<Yantra::FeatureExtractor<>>(
880 static_cast<uint32_t
>(window_size),
static_cast<uint32_t
>(hop_size),
882 e->set_parameter(
"overlap",
double(hop_size) / (double)window_size);
884 auto extracted = e->apply_operation(input).
data[0];
885 std::vector<std::vector<double>> segments;
886 for (
size_t i = 0; i < extracted.size(); i += window_size) {
887 size_t end = std::min(i + window_size, extracted.size());
888 segments.emplace_back(extracted.begin() + i, extracted.begin() + end);
893std::vector<std::vector<std::vector<double>>>
windowed_segments_per_channel(
const std::vector<Kakshya::DataVariant>& channels,
size_t window_size,
size_t hop_size)
895 std::vector<std::vector<std::vector<double>>> all_segments;
896 all_segments.reserve(channels.size());
897 for (
const auto& ch : channels)
902std::vector<std::pair<size_t, size_t>>
detect_silence(
const std::vector<double>& data,
double threshold,
size_t min_silence_duration)
904 static const auto s_op = [] {
905 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
909 s_op->set_parameter(
"silence_threshold", threshold);
910 s_op->set_parameter(
"min_duration",
static_cast<uint32_t
>(min_silence_duration));
912 auto result = s_op->apply_operation(input);
913 auto pos = result.template get_metadata<std::vector<std::pair<size_t, size_t>>>(
"window_positions");
914 return pos.has_value() ? pos.value() : std::vector<std::pair<size_t, size_t>> {};
919 static const auto s_op = [] {
920 auto e = std::make_shared<Yantra::FeatureExtractor<>>();
924 s_op->set_parameter(
"silence_threshold", threshold);
925 s_op->set_parameter(
"min_duration",
static_cast<uint32_t
>(min_silence_duration));
927 auto result = s_op->apply_operation(input);
928 auto pos = result.template get_metadata<std::vector<std::pair<size_t, size_t>>>(
"window_positions");
929 return pos.has_value() ? pos.value() : std::vector<std::pair<size_t, size_t>> {};
932std::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)
934 std::vector<std::vector<std::pair<size_t, size_t>>> all_regions;
935 all_regions.reserve(channels.size());
936 for (
const auto& ch : channels)
937 all_regions.push_back(
detect_silence(ch, threshold, min_silence_duration));
945std::vector<double>
mix(
const std::vector<std::vector<double>>& streams)
950 size_t max_length = 0;
951 for (
const auto& s : streams)
952 max_length = std::max(max_length, s.size());
954 std::vector<double> result(max_length, 0.0);
955 for (
const auto& s : streams) {
956 for (
size_t i = 0; i < s.size(); ++i)
960 apply_gain(result, 1.0 /
static_cast<double>(streams.size()));
964std::vector<double>
mix(
const std::vector<Kakshya::DataVariant>& streams)
971 if (is_same_size(numeric_data)) {
972 std::vector<double> result(numeric_data[0].
size(), 0.0);
973 for (
const auto& span : numeric_data) {
974 for (
size_t i = 0; i < span.size(); ++i)
975 result[i] += span[i];
977 apply_gain(result, 1.0 /
static_cast<double>(numeric_data.size()));
981 std::vector<std::vector<double>> double_streams;
982 double_streams.reserve(streams.size());
983 for (
const auto& span : numeric_data)
984 double_streams.emplace_back(span.begin(), span.end());
985 return mix(double_streams);
988std::vector<double>
mix_with_gains(
const std::vector<std::vector<double>>& streams,
const std::vector<double>& gains)
990 if (streams.empty() || gains.size() != streams.size()) {
992 "Streams and gains vectors must have the same size");
995 size_t max_length = 0;
996 for (
const auto& s : streams)
997 max_length = std::max(max_length, s.size());
999 std::vector<double> result(max_length, 0.0);
1000 for (
size_t s = 0; s < streams.size(); ++s) {
1001 for (
size_t i = 0; i < streams[s].size(); ++i)
1002 result[i] += streams[s][i] * gains[s];
1007std::vector<double>
mix_with_gains(
const std::vector<Kakshya::DataVariant>& streams,
const std::vector<double>& gains)
1009 if (streams.empty() || gains.size() != streams.size()) {
1011 "Streams and gains vectors must have the same size");
1016 if (is_same_size(numeric_data)) {
1017 std::vector<double> result(numeric_data[0].
size(), 0.0);
1018 for (
size_t s = 0; s < numeric_data.size(); ++s) {
1019 for (
size_t i = 0; i < numeric_data[s].size(); ++i)
1020 result[i] += numeric_data[s][i] * gains[s];
1025 std::vector<std::vector<double>> double_streams;
1026 double_streams.reserve(streams.size());
1027 for (
const auto& span : numeric_data)
1028 double_streams.emplace_back(span.begin(), span.end());
1035 return span.empty() ? std::vector<double> {} : std::vector<double>(span.begin(), span.end());
1043std::vector<std::vector<double>>
to_double_vectors(
const std::vector<Kakshya::DataVariant>& channels)
1046 std::vector<std::vector<double>> result;
1047 result.reserve(spans.size());
1048 for (
const auto& span : spans)
1049 result.emplace_back(span.begin(), span.end());
1053std::vector<Kakshya::DataVariant>
to_data_variants(
const std::vector<std::vector<double>>& channel_data)
1055 std::vector<Kakshya::DataVariant> result;
1056 result.reserve(channel_data.size());
1057 for (
const auto& ch : channel_data)
1058 result.emplace_back(ch);
Discrete sequence analysis primitives for MayaFlux::Kinesis.
Span-based energy analysis for digital signals in Maya Flux.
std::optional< size_t > times
Data analysis and transformation convenience API.
static std::span< double > extract_numeric_data(const T &compute_data)
extract numeric data from single-variant types
@ API
API calls from external code.
@ API
MayaFlux/API Wrapper and convenience functions.
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.
void linear(std::span< double > data, double a, double b) noexcept
Linear map y = a*x + b applied in-place.
void reverse(std::span< double > data) noexcept
Reverse temporal order in-place.
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.
void normalize(std::span< double > data, double target_min, double target_max) noexcept
Normalize to [target_min, target_max] in-place Single-pass min/max reduction followed by a single tra...
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)
@ SILENCE_DATA
Extract actual silent regions.
@ ZERO_CROSSING_DATA
Extract actual data at zero crossing points.
@ OVERLAPPING_WINDOWS
Extract overlapping windowed data.
@ STD_DEV
Standard deviation.
std::vector< std::vector< double > > to_double_vectors(const std::vector< Kakshya::DataVariant > &channels)
Convert multi-channel data to vector of double vectors.
std::vector< size_t > zero_crossings(const std::vector< double > &data, double threshold)
Detect zero crossings in single-channel signal.
Kakshya::DataVariant to_data_variant(const std::vector< double > &data)
Convert vector<double> to DataVariant.
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.
std::vector< Kakshya::DataVariant > with_gain_channels(const std::vector< Kakshya::DataVariant > &channels, double gain_factor)
Apply gain to multi-channel data (non-destructive)
std::vector< double > dynamic_range_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate dynamic range per channel for multi-channel data.
double std_dev_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate standard deviation across all channels (mix then analyze)
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.
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.
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.
std::vector< Kakshya::DataVariant > reversed_channels(const std::vector< Kakshya::DataVariant > &channels)
Reverse time order of multi-channel data (non-destructive)
std::vector< double > peak_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Find peak amplitude per channel for multi-channel data.
double zero_crossing_rate(const std::vector< double > &data, size_t window_size)
Calculate zero crossing rate for single-channel data.
void reverse(std::vector< double > &data)
Reverse time order of single-channel data (in-place)
std::vector< double > mean_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate mean per channel for multi-channel data.
void apply_gain_channels(std::vector< Kakshya::DataVariant > &channels, double gain_factor)
Apply gain to multi-channel data (in-place)
void normalize_together(std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize multi-channel data relative to global peak (in-place)
std::vector< double > to_double_vector(const Kakshya::DataVariant &data)
Convert DataVariant to vector<double> if possible.
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.
std::vector< double > with_gain(const std::vector< double > &data, double gain_factor)
Apply gain to single-channel data (non-destructive)
double dynamic_range(const std::vector< double > &data)
Calculate dynamic range (max/min ratio in dB) of single-channel data.
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.
double rms(const std::vector< double > &data)
Calculate RMS (Root Mean Square) energy of single-channel data.
void normalize_channels(std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize each channel independently to specified peak level (in-place)
void reverse_channels(std::vector< Kakshya::DataVariant > &channels)
Reverse time order of multi-channel data (in-place)
double peak_channel(const std::vector< Kakshya::DataVariant > &channels, size_t channel_index)
Find peak amplitude in specific channel.
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.
std::vector< double > std_dev_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate standard deviation per channel for multi-channel data.
std::vector< double > reversed(const std::vector< double > &data)
Reverse time order of single-channel data (non-destructive)
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.
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.
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.
double dynamic_range_global(const std::vector< Kakshya::DataVariant > &channels)
Calculate dynamic range across all channels (global min/max)
std::vector< double > magnitude_spectrum(const std::vector< double > &data, size_t window_size)
Compute magnitude spectrum for single-channel data.
void apply_window_channels(std::vector< Kakshya::DataVariant > &channels, const std::string &window_type)
Apply window function to multi-channel data (in-place)
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.
void normalize(std::vector< double > &data, double target_peak)
Normalize single-channel data to specified peak level (in-place)
void apply_window(std::vector< double > &data, const std::string &window_type)
Apply window function to single-channel data (in-place)
double rms_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate RMS energy across all channels (mix then analyze)
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.
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.
std::vector< Kakshya::DataVariant > normalized_channels(const std::vector< Kakshya::DataVariant > &channels, double target_peak)
Normalize each channel independently (non-destructive)
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.
double spectral_centroid(const std::vector< double > &data, double sample_rate)
Find spectral centroid (brightness measure) for single-channel data.
void initialize_yantra()
Initialize Yantra subsystem with default configuration.
double std_dev(const std::vector< double > &data)
Calculate standard deviation of single-channel data.
std::vector< double > normalized(const std::vector< double > &data, double target_peak)
Normalize single-channel data (non-destructive)
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.
double mean_combined(const std::vector< Kakshya::DataVariant > &channels)
Calculate mean across all channels (mix then analyze)
std::vector< double > detect_onsets(const std::vector< double > &data, double sample_rate, double threshold)
Detect onset times in single-channel signal.
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.
double peak(const std::vector< double > &data)
Find peak amplitude in single-channel data.
void apply_gain(std::vector< double > &data, double gain_factor)
Apply gain to single-channel data (in-place)
void apply_gain_per_channel(std::vector< Kakshya::DataVariant > &channels, const std::vector< double > &gain_factors)
Apply different gain to each channel (in-place)
std::vector< double > mix(const std::vector< std::vector< double > > &streams)
Mix multiple data streams with equal weighting.
std::vector< double > rms_per_channel(const std::vector< Kakshya::DataVariant > &channels)
Calculate RMS energy per channel for multi-channel data.
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.
std::vector< double > power_spectrum(const std::vector< double > &data, size_t window_size)
Compute power spectrum for single-channel data.
Main namespace for the Maya Flux audio engine.
T data
The actual computation data.
Input/Output container for computation pipeline data flow with structure preservation.