Create comprehensive analysis result from energy computation.
425 {
426 EnergyAnalysis result;
430
431 if (energy_values.empty()) {
432 return result;
433 }
434
435 result.channels.resize(energy_values.size());
436
437 for (size_t ch = 0; ch < energy_values.size(); ch++) {
438
439 auto& channel_result = result.channels[ch];
440 const auto& ch_energy = energy_values[ch];
441
442 channel_result.energy_values = ch_energy;
443
444 if (!ch_energy.empty()) {
445 auto [min_it, max_it] = std::ranges::minmax_element(ch_energy);
446 channel_result.min_energy = *min_it;
447 channel_result.max_energy = *max_it;
448
449 const double sum = std::accumulate(ch_energy.begin(), ch_energy.end(), 0.0);
450 channel_result.mean_energy = sum / static_cast<double>(ch_energy.size());
451
452 const double mean = channel_result.mean_energy;
453 const double var_sum = std::transform_reduce(
454 ch_energy.begin(), ch_energy.end(), 0.0, std::plus {},
455 [
mean](
double val) { return (val - mean) * (val - mean); });
456 channel_result.variance = var_sum / static_cast<double>(ch_energy.size());
457 }
458
459 const size_t data_size = (ch < original_data.size()) ? original_data[ch].size() : 0;
460 channel_result.window_positions.reserve(ch_energy.size());
461
462 for (size_t i = 0; i < ch_energy.size(); ++i) {
464 const size_t end = std::min(start +
m_window_size, data_size);
465 channel_result.window_positions.emplace_back(start, end);
466 }
467
468 if (ch < original_data.size()) {
472 original_data[ch], 0.0);
473 break;
474
478 original_data[ch], peak_threshold,
m_hop_size / 4);
479 break;
480 }
481
487 default:
488
489 break;
490 }
491 }
492
494 channel_result.classifications.reserve(ch_energy.size());
495 channel_result.level_counts.fill(0);
496
497 for (double energy : ch_energy) {
499 channel_result.classifications.push_back(level);
500 channel_result.level_counts[static_cast<size_t>(level)]++;
501 }
502 }
503 }
504
505 return result;
506 }
EnergyLevel classify_energy_level(double energy) const
Classify energy value into qualitative level.
bool m_classification_enabled
@ SPECTRAL
Spectral energy (FFT-based)
@ DYNAMIC_RANGE
Dynamic range (dB)
@ RMS
Root Mean Square energy.
@ ZERO_CROSSING
Zero-crossing rate.
@ HARMONIC
Harmonic energy (low-frequency content)
@ POWER
Power (sum of squares)
EnergyLevel
Qualitative classification of energy values.
std::vector< size_t > find_peak_positions(std::span< const double > data, double threshold, size_t min_distance)
Find actual peak positions in the signal.
std::vector< size_t > find_zero_crossing_positions(std::span< const double > data, double threshold)
Find actual zero-crossing positions in the signal.
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.