51{
52 std::vector<std::vector<double>> result;
53 result.reserve(data.size());
54
55 for (const auto& channel : data) {
56 if (channel.empty()) {
57 result.emplace_back();
58 continue;
59 }
60
61 uint32_t effective_window_size = std::min(window_size, static_cast<uint32_t>(channel.size()));
62 uint32_t effective_hop_size = std::min(hop_size, effective_window_size / 2);
63 if (effective_hop_size == 0)
64 effective_hop_size = 1;
65
66 if (!validate_extraction_parameters(effective_window_size, effective_hop_size, channel.size())) {
67 result.emplace_back();
68 continue;
69 }
70
71 try {
72 auto energy_analyzer = std::make_shared<EnergyAnalyzer<std::vector<Kakshya::DataVariant>, Eigen::VectorXd>>(
73 effective_window_size, effective_hop_size);
74 energy_analyzer->set_parameter("method", "rms");
75
76 std::vector<Kakshya::DataVariant> data_variant { Kakshya::DataVariant { std::vector<double>(channel.begin(), channel.end()) } };
77 EnergyAnalysis energy_result = energy_analyzer->analyze_energy(data_variant);
78
79 if (energy_result.channels.empty() || energy_result.channels[0].energy_values.empty() || energy_result.channels[0].window_positions.empty()) {
80 result.emplace_back();
81 continue;
82 }
83
84 std::vector<std::pair<size_t, size_t>> qualifying_windows;
85 const auto& ch_energy = energy_result.channels[0].energy_values;
86 const auto& ch_windows = energy_result.channels[0].window_positions;
87 for (size_t i = 0; i < ch_energy.size(); ++i) {
88 if (ch_energy[i] > energy_threshold) {
89 auto [start_idx, end_idx] = ch_windows[i];
90 if (start_idx < channel.size() && end_idx <= channel.size() && start_idx < end_idx) {
91 qualifying_windows.emplace_back(start_idx, end_idx);
92 }
93 }
94 }
95
96 auto merged_windows = merge_overlapping_windows(qualifying_windows);
97
98 std::vector<double> extracted_data;
99 for (const auto& [start_idx, end_idx] : merged_windows) {
100 std::ranges::copy(channel.subspan(start_idx, end_idx - start_idx),
101 std::back_inserter(extracted_data));
102 }
103
104 result.push_back(std::move(extracted_data));
105 } catch (const std::exception&) {
106 result.emplace_back();
107 }
108 }
109
110 return result;
111}