Create comprehensive analysis result from energy computation.
427 {
428 EnergyAnalysis result;
432
433 if (energy_values.empty()) {
434 return result;
435 }
436
437 result.channels.resize(energy_values.size());
438
439 for (size_t ch = 0; ch < energy_values.size(); ch++) {
440
441 auto& channel_result = result.channels[ch];
442 const auto& ch_energy = energy_values[ch];
443
444 channel_result.energy_values = ch_energy;
445
446 if (!ch_energy.empty()) {
447 auto [min_it, max_it] = std::ranges::minmax_element(ch_energy);
448 channel_result.min_energy = *min_it;
449 channel_result.max_energy = *max_it;
450
451 const double sum = std::accumulate(ch_energy.begin(), ch_energy.end(), 0.0);
452 channel_result.mean_energy =
sum /
static_cast<double>(ch_energy.size());
453
454 const double mean = channel_result.mean_energy;
455 const double var_sum = std::transform_reduce(
456 ch_energy.begin(), ch_energy.end(), 0.0, std::plus {},
457 [
mean](
double val) { return (val - mean) * (val - mean); });
458 channel_result.variance = var_sum / static_cast<double>(ch_energy.size());
459 }
460
461 const size_t data_size = (ch < original_data.size()) ? original_data[ch].size() : 0;
462 channel_result.window_positions.reserve(ch_energy.size());
463
464 for (size_t i = 0; i < ch_energy.size(); ++i) {
466 const size_t end = std::min(start +
m_window_size, data_size);
467 channel_result.window_positions.emplace_back(start, end);
468 }
469
470 if (ch < original_data.size()) {
474 original_data[ch], 0.0);
475 break;
476
480 original_data[ch], peak_threshold,
m_hop_size / 4);
481 break;
482 }
483
489 default:
490
491 break;
492 }
493 }
494
496 channel_result.classifications.reserve(ch_energy.size());
497 channel_result.level_counts.fill(0);
498
499 for (double energy : ch_energy) {
501 channel_result.classifications.push_back(level);
502 channel_result.level_counts[static_cast<size_t>(level)]++;
503 }
504 }
505 }
506
507 return result;
508 }
EnergyLevel classify_energy_level(double energy) const
Classify energy value into qualitative level.
bool m_classification_enabled
std::vector< size_t > zero_crossing_positions(std::span< const double > data, double threshold)
Sample indices of zero crossings in the full span.
std::vector< size_t > peak_positions(std::span< const double > data, double threshold, size_t min_distance)
Sample indices of local peak maxima in the full span.
std::vector< double > sum(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Sum per window.
@ 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.
double mean(const std::vector< double > &data)
Calculate mean of single-channel data.