Create comprehensive analysis result from energy computation.
434 {
435 EnergyAnalysis result;
439
440 if (energy_values.empty()) {
441 return result;
442 }
443
444 result.channels.resize(energy_values.size());
445
446 for (size_t ch = 0; ch < energy_values.size(); ch++) {
447
448 auto& channel_result = result.channels[ch];
449 const auto& ch_energy = energy_values[ch];
450
451 channel_result.energy_values = ch_energy;
452
453 if (!ch_energy.empty()) {
454 auto [min_it, max_it] = std::ranges::minmax_element(ch_energy);
455 channel_result.min_energy = *min_it;
456 channel_result.max_energy = *max_it;
457
458 const double sum = std::accumulate(ch_energy.begin(), ch_energy.end(), 0.0);
459 channel_result.mean_energy =
sum /
static_cast<double>(ch_energy.size());
460
461 const double mean = channel_result.mean_energy;
462 const double var_sum = std::transform_reduce(
463 ch_energy.begin(), ch_energy.end(), 0.0, std::plus {},
464 [
mean](
double val) { return (val - mean) * (val - mean); });
465 channel_result.variance = var_sum / static_cast<double>(ch_energy.size());
466 }
467
468 const size_t data_size = (ch < original_data.size()) ? original_data[ch].
size() : 0;
469 channel_result.window_positions.reserve(ch_energy.size());
470
471 for (size_t i = 0; i < ch_energy.size(); ++i) {
473 const size_t end = std::min(start +
m_window_size, data_size);
474 channel_result.window_positions.emplace_back(start, end);
475 }
476
477 if (ch < original_data.size()) {
481 original_data[ch], 0.0);
482 break;
483
487 original_data[ch], peak_threshold,
m_hop_size / 4);
488 break;
489 }
490
496 default:
497
498 break;
499 }
500 }
501
503 channel_result.classifications.reserve(ch_energy.size());
504 channel_result.level_counts.fill(0);
505
506 for (double energy : ch_energy) {
508 channel_result.classifications.push_back(level);
509 channel_result.level_counts[static_cast<size_t>(level)]++;
510 }
511 }
512 }
513
514 return result;
515 }
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.