558{
559 std::vector<std::vector<double>> result;
560 result.reserve(data.size());
561
562 for (const auto& channel : data) {
563 if (channel.empty()) {
564 result.emplace_back();
565 continue;
566 }
567
568 uint32_t effective_window = std::min(window_size, static_cast<uint32_t>(channel.size()));
569 uint32_t effective_hop = std::max(1U, std::min(hop_size, window_size / 2));
570
571 try {
572 auto analyzer = std::make_shared<EnergyAnalyzer<std::vector<Kakshya::DataVariant>, Eigen::VectorXd>>(
573 effective_window, effective_hop);
574 analyzer->set_parameter("method", "rms");
575 analyzer->set_energy_thresholds(0.0, silence_threshold, silence_threshold * 2.0, silence_threshold * 5.0);
576 analyzer->enable_classification(true);
577
578 std::vector<Kakshya::DataVariant> data_variant {
Kakshya::DataVariant { std::vector<double>(channel.begin(), channel.end()) } };
579 EnergyAnalysis energy_result = analyzer->analyze_energy(data_variant);
580
581 if (energy_result.channels.empty() || energy_result.channels[0].energy_values.empty() || energy_result.channels[0].window_positions.empty() || energy_result.channels[0].classifications.empty()) {
582 result.emplace_back();
583 continue;
584 }
585
586 const auto& classifications = energy_result.channels[0].classifications;
587 const auto& window_positions = energy_result.channels[0].window_positions;
588
589 std::vector<std::pair<size_t, size_t>> regions;
590 for (size_t idx = 0; idx < classifications.size(); ++idx) {
591 if (classifications[idx] == EnergyLevel::SILENT) {
592 auto [start_idx, end_idx] = window_positions[idx];
593 if (end_idx > start_idx && (end_idx - start_idx) >= min_duration) {
594 regions.emplace_back(start_idx, end_idx);
595 }
596 }
597 }
598
599 auto merged_regions = merge_overlapping_windows(regions);
600
601 std::vector<double> extracted_data;
602 for (const auto& [start_idx, end_idx] : merged_regions) {
603 if (start_idx < channel.size() && end_idx <= channel.size() && start_idx < end_idx) {
604 auto region = channel.subspan(start_idx, end_idx - start_idx);
605 std::ranges::copy(region, std::back_inserter(extracted_data));
606 }
607 }
608
609 result.push_back(std::move(extracted_data));
610 } catch (const std::exception&) {
611 result.emplace_back();
612 }
613 }
614
615 return result;
616}
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.