MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
EnergyAnalyzer.hpp
Go to the documentation of this file.
1#pragma once
2
5
7#include <Eigen/Dense>
8
10
12
13/**
14 * @file EnergyAnalyzer.hpp
15 * @brief Span-based energy analysis for digital signals in Maya Flux
16 *
17 * Defines the EnergyAnalyzer using the new UniversalAnalyzer framework with
18 * zero-copy span processing and automatic structure handling via OperationHelper.
19 * This analyzer extracts energy-related features from digital signals with multiple
20 * computation methods and flexible output configurations.
21 *
22 * Key Features:
23 * - **Zero-copy processing:** Uses spans for maximum efficiency
24 * - **Template-flexible I/O:** Instance defines input/output types at construction
25 * - **Multiple energy methods:** RMS, peak, spectral, zero-crossing, harmonic, power, dynamic range
26 * - **Parallel processing:** Utilizes std::execution for performance
27 * - **Energy classification:** Maps values to qualitative levels (silent, quiet, etc.)
28 * - **Window-based analysis:** Configurable window size and hop size
29 * - **Automatic data handling:** OperationHelper manages all extraction/conversion
30 */
31
32namespace MayaFlux::Yantra {
33
34/**
35 * @enum EnergyMethod
36 * @brief Supported energy computation methods
37 */
38enum class EnergyMethod : uint8_t {
39 RMS, ///< Root Mean Square energy
40 PEAK, ///< Peak amplitude
41 SPECTRAL, ///< Spectral energy (FFT-based)
42 ZERO_CROSSING, ///< Zero-crossing rate
43 HARMONIC, ///< Harmonic energy (low-frequency content)
44 POWER, ///< Power (sum of squares)
45 DYNAMIC_RANGE ///< Dynamic range (dB)
46};
47
48/**
49 * @enum EnergyLevel
50 * @brief Qualitative classification of energy values
51 */
52enum class EnergyLevel : uint8_t {
53 SILENT,
54 QUIET,
56 LOUD,
57 PEAK
58};
59
60struct MAYAFLUX_API ChannelEnergy {
61 std::vector<double> energy_values;
62 double mean_energy {};
63 double max_energy {};
64 double min_energy {};
65 double variance {};
66
67 std::vector<EnergyLevel> classifications;
68 std::array<int, 5> level_counts {}; // [SILENT, QUIET, MODERATE, LOUD, PEAK]
69 std::vector<std::pair<size_t, size_t>> window_positions;
70
71 // Positions of detected energy events (e.g., peaks, zero crossings, flux)
72 std::vector<size_t> event_positions;
73};
74
75/**
76 * @struct EnergyAnalysis
77 * @brief Analysis result structure for energy analysis
78 */
79struct MAYAFLUX_API EnergyAnalysis {
80 std::vector<ChannelEnergy> channels;
81
82 EnergyMethod method_used {};
83 uint32_t window_size {};
84 uint32_t hop_size {};
85};
86
87/**
88 * @struct EnergyAnalyzerConfig
89 * @brief Initial settings for energy analysis.
90 *
91 * Pass this aggregate with designated initializers to the config constructor.
92 * Named parameters are applied after the typed settings.
93 */
95 /** Analysis window length in samples. */
96 uint32_t window_size { 256 };
97 /** Distance between successive windows in samples. */
98 uint32_t hop_size { 128 };
99 /** Energy calculation to perform. */
101 /** Whether to classify energy levels. */
103 /** Silent, quiet, moderate, and loud boundaries, in that order. */
104 std::array<double, 4> thresholds { 0.01, 0.1, 0.5, 0.8 };
105 /** Level at which the analyzer processes input. */
107 /** Additional named parameters applied last. */
108 std::map<std::string, std::any> parameters;
109};
110
111/**
112 * @class EnergyAnalyzer
113 * @brief High-performance energy analyzer with zero-copy processing
114 *
115 * The EnergyAnalyzer provides comprehensive energy analysis capabilities for
116 * digital signals using span-based processing for maximum efficiency.
117 * All data extraction and conversion is handled automatically by OperationHelper.
118 *
119 * Example usage:
120 * ```cpp
121 * // DataVariant -> VectorXd analyzer
122 * auto energy_analyzer = std::make_shared<EnergyAnalyzer<Kakshya::DataVariant, Eigen::VectorXd>>();
123 *
124 * // User-facing analysis
125 * auto analysis = energy_analyzer->analyze_data(audio_data);
126 * auto energy_result = safe_any_cast<EnergyAnalysis>(analysis);
127 *
128 * // Pipeline usage
129 * auto pipeline_output = energy_analyzer->apply_operation(IO{audio_data});
130 * ```
131 */
132template <ComputeData InputType = std::vector<Kakshya::DataVariant>, ComputeData OutputType = Eigen::VectorXd>
133class EnergyAnalyzer : public UniversalAnalyzer<InputType, OutputType> {
134public:
138
139 /**
140 * @brief Construct EnergyAnalyzer with configurable window parameters
141 * @param window_size Size of analysis window in samples (default: 512)
142 * @param hop_size Step size between windows in samples (default: 256)
143 */
144 explicit EnergyAnalyzer(uint32_t window_size = 256, uint32_t hop_size = 128)
145 : m_window_size(window_size)
146 , m_hop_size(hop_size)
147 {
149 }
150
151 /**
152 * @brief Construct and configure an energy analyzer in one step.
153 * @param config Initial analysis settings.
154 */
155 explicit EnergyAnalyzer(const EnergyAnalyzerConfig& config)
156 : EnergyAnalyzer(config.window_size, config.hop_size)
157 {
161 config.thresholds[0],
162 config.thresholds[1],
163 config.thresholds[2],
164 config.thresholds[3]);
166
167 for (const auto& [name, value] : config.parameters) {
168 this->set_parameter(name, value);
169 }
170 }
171
172 /**
173 * @brief Type-safe energy analysis method
174 * @param data Input data
175 * @return EnergyAnalysis directly
176 */
178 {
179 auto result = this->analyze_data(data);
180 return safe_any_cast_or_throw<EnergyAnalysis>(result);
181 }
182
183 EnergyAnalysis analyze_energy(const InputType& data)
184 {
185 return this->analyze_energy(input_type { data });
186 }
187
188 /**
189 * @brief Get last energy analysis result (type-safe)
190 * @return EnergyAnalysis from last operation
191 */
193 {
194 return safe_any_cast_or_throw<EnergyAnalysis>(this->get_current_analysis());
195 }
196
197 /**
198 * @brief Get analysis type category
199 * @return AnalysisType::FEATURE (energy is a feature extraction operation)
200 */
201 [[nodiscard]] AnalysisType get_analysis_type() const override
202 {
204 }
205
206 /**
207 * @brief Get available analysis methods
208 * @return Vector of supported energy method names
209 */
210 [[nodiscard]] std::vector<std::string> get_available_methods() const override
211 {
212 return Reflect::get_enum_names_lowercase<EnergyMethod>();
213 }
214
215 /**
216 * @brief Check if a specific method is supported
217 * @param method Method name to check
218 * @return True if method is supported
219 */
220 [[nodiscard]] bool supports_method(const std::string& method) const override
221 {
222 return std::find_if(get_available_methods().begin(), get_available_methods().end(),
223 [&method](const std::string& m) {
224 return std::equal(method.begin(), method.end(), m.begin(), m.end(),
225 [](char a, char b) { return std::tolower(a) == std::tolower(b); });
226 })
227 != get_available_methods().end();
228 }
229
230 /**
231 * @brief Set energy computation method
232 */
233 void set_energy_method(EnergyMethod method) { m_method = method; }
234
235 /**
236 * @brief Get current energy computation method
237 */
238 [[nodiscard]] EnergyMethod get_energy_method() const { return m_method; }
239
240 /**
241 * @brief Set window parameters for analysis
242 * @param window_size Window size in samples
243 * @param hop_size Hop size in samples
244 */
245 void set_window_parameters(uint32_t window_size, uint32_t hop_size)
246 {
247 m_window_size = window_size;
248 m_hop_size = hop_size;
250 }
251
252 /**
253 * @brief Set energy level classification thresholds
254 * @param silent Threshold for silent level
255 * @param quiet Threshold for quiet level
256 * @param moderate Threshold for moderate level
257 * @param loud Threshold for loud level
258 */
259 void set_energy_thresholds(double silent, double quiet, double moderate, double loud)
260 {
261 if (silent >= quiet || quiet >= moderate || moderate >= loud) {
262 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Energy thresholds must be in ascending order");
263 }
264 m_silent_threshold = silent;
265 m_quiet_threshold = quiet;
266 m_moderate_threshold = moderate;
267 m_loud_threshold = loud;
268 }
269
270 /**
271 * @brief Enable or disable energy level classification
272 * @param enabled True to enable classification
273 */
274 void enable_classification(bool enabled) { m_classification_enabled = enabled; }
275
276 /**
277 * @brief Classify energy value into qualitative level
278 * @param energy Energy value to classify
279 * @return EnergyLevel classification
280 */
281 [[nodiscard]] EnergyLevel classify_energy_level(double energy) const
282 {
283 if (energy <= m_silent_threshold)
284 return EnergyLevel::SILENT;
285 if (energy <= m_quiet_threshold)
286 return EnergyLevel::QUIET;
287 if (energy <= m_moderate_threshold)
289 if (energy <= m_loud_threshold)
290 return EnergyLevel::LOUD;
291 return EnergyLevel::PEAK;
292 }
293
294 /**
295 * @brief Get count of windows in a specific energy level for a channel
296 * @param channel ChannelEnergy result
297 * @param level EnergyLevel to query
298 * @return Count of windows in that level
299 */
300 [[nodiscard]]
301 int get_level_count(const ChannelEnergy& channel, EnergyLevel level)
302 {
303 return channel.level_counts[static_cast<size_t>(level)];
304 }
305
306 /**
307 * @brief Convert energy method enum to string
308 * @param method EnergyMethod value
309 * @return String representation
310 */
311 static std::string method_to_string(EnergyMethod method)
312 {
314 }
315
316 /**
317 * @brief Convert string to energy method enum
318 * @param str String representation
319 * @return EnergyMethod value
320 */
321 static EnergyMethod string_to_method(const std::string& str)
322 {
323 if (str == "default")
324 return EnergyMethod::RMS;
325 return Reflect::string_to_enum_or_throw_case_insensitive<EnergyMethod>(str, "EnergyMethod");
326 }
327
328 /**
329 * @brief Convert energy level enum to string
330 * @param level EnergyLevel value
331 * @return String representation
332 */
333 static std::string energy_level_to_string(EnergyLevel level)
334 {
336 }
337
338protected:
339 /**
340 * @brief Get analyzer name
341 * @return "EnergyAnalyzer"
342 */
343 [[nodiscard]] std::string get_analyzer_name() const override
344 {
345 return "EnergyAnalyzer";
346 }
347
348 /**
349 * @brief Core analysis implementation - creates analysis result AND pipeline output
350 * @param input Input data wrapped in Datum container
351 * @return Pipeline output (data flow for chaining operations)
352 */
354 {
355 try {
356 auto [data_span, structure_info] = OperationHelper::extract_structured_double(
357 const_cast<input_type&>(input));
358
359 std::vector<std::span<const double>> channel_spans;
360 for (auto& span : data_span)
361 channel_spans.emplace_back(span.data(), span.size());
362
363 for (const auto& channel_span : channel_spans) {
364 if (channel_span.size() < m_window_size) {
365 error<std::runtime_error>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "One or more channels in input data are smaller than window size ({} samples)", m_window_size);
366 }
367 }
368
369 std::vector<std::vector<double>> energy_values;
370 energy_values.reserve(channel_spans.size());
371 for (const auto& channel_span : channel_spans) {
372 energy_values.push_back(compute_energy_values(channel_span, m_method));
373 }
374
375 EnergyAnalysis analysis_result = create_analysis_result(
376 energy_values, channel_spans, structure_info);
377
378 this->store_current_analysis(analysis_result);
379
380 return create_pipeline_output(input, analysis_result, structure_info);
381 } catch (const std::exception& e) {
382 MF_ERROR(Journal::Component::Yantra, Journal::Context::ComputeMatrix, "Energy analysis failed: {}", e.what());
383 output_type error_result;
384 error_result.metadata = input.metadata;
385 error_result.metadata["error"] = std::string("Analysis failed: ") + e.what();
386 return error_result;
387 }
388 }
389
390 /**
391 * @brief Handle analysis-specific parameters
392 */
393 void set_analysis_parameter(const std::string& name, std::any value) override
394 {
395 if (name == "method") {
396 if (auto str_result = safe_any_cast<std::string>(value)) {
397 m_method = string_to_method(*str_result.value);
398 return;
399 }
400
401 if (auto enum_result = safe_any_cast<EnergyMethod>(value)) {
402 m_method = *enum_result.value;
403 return;
404 }
405
407 std::source_location::current(),
408 "Invalid method parameter - expected string or EnergyMethod enum");
409 } else if (name == "window_size") {
410 if (auto result = safe_any_cast<uint32_t>(value)) {
411 m_window_size = *result.value;
413 return;
414 }
415 } else if (name == "hop_size") {
416 if (auto result = safe_any_cast<uint32_t>(value)) {
417 m_hop_size = *result.value;
419 return;
420 }
421 } else if (name == "classification_enabled") {
422 if (auto result = safe_any_cast<bool>(value)) {
423 m_classification_enabled = *result.value;
424 return;
425 }
426 }
427
429 }
430
431 /**
432 * @brief Get analysis-specific parameter
433 */
434 [[nodiscard]] std::any get_analysis_parameter(const std::string& name) const override
435 {
436 if (name == "method")
437 return std::any(method_to_string(m_method));
438 if (name == "window_size")
439 return std::any(m_window_size);
440 if (name == "hop_size")
441 return std::any(m_hop_size);
442 if (name == "classification_enabled")
443 return std::any(m_classification_enabled);
444
446 }
447
448private:
449 uint32_t m_window_size { 512 };
450 uint32_t m_hop_size { 256 };
453
454 double m_silent_threshold { 0.01 };
455 double m_quiet_threshold = { 0.1 };
456 double m_moderate_threshold { 0.5 };
457 double m_loud_threshold { 0.8 };
458
460 {
461 if (m_window_size == 0) {
462 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Window size must be greater than 0");
463 }
464 if (m_hop_size == 0) {
465 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Hop size must be greater than 0");
466 }
468 error<std::invalid_argument>(Journal::Component::Yantra, Journal::Context::ComputeMatrix, std::source_location::current(), "Hop size should not exceed window size");
469 }
470 }
471
472 /**
473 * @brief Create comprehensive analysis result from energy computation
474 */
476 const std::vector<std::vector<double>>& energy_values,
477 std::vector<std::span<const double>> original_data,
478 const DataStructureInfo& /*structure_info*/) const
479 {
480 EnergyAnalysis result;
481 result.method_used = m_method;
482 result.window_size = m_window_size;
483 result.hop_size = m_hop_size;
484
485 if (energy_values.empty()) {
486 return result;
487 }
488
489 result.channels.resize(energy_values.size());
490
491 for (size_t ch = 0; ch < energy_values.size(); ch++) {
492
493 auto& channel_result = result.channels[ch];
494 const auto& ch_energy = energy_values[ch];
495
496 channel_result.energy_values = ch_energy;
497
498 if (!ch_energy.empty()) {
499 auto [min_it, max_it] = std::ranges::minmax_element(ch_energy);
500 channel_result.min_energy = *min_it;
501 channel_result.max_energy = *max_it;
502
503 const double sum = std::accumulate(ch_energy.begin(), ch_energy.end(), 0.0);
504 channel_result.mean_energy = sum / static_cast<double>(ch_energy.size());
505
506 const double mean = channel_result.mean_energy;
507 const double var_sum = std::transform_reduce(
508 ch_energy.begin(), ch_energy.end(), 0.0, std::plus {},
509 [mean](double val) { return (val - mean) * (val - mean); });
510 channel_result.variance = var_sum / static_cast<double>(ch_energy.size());
511 }
512
513 const size_t data_size = (ch < original_data.size()) ? original_data[ch].size() : 0;
514 channel_result.window_positions.reserve(ch_energy.size());
515
516 for (size_t i = 0; i < ch_energy.size(); ++i) {
517 const size_t start = i * m_hop_size;
518 const size_t end = std::min(start + m_window_size, data_size);
519 channel_result.window_positions.emplace_back(start, end);
520 }
521
522 if (ch < original_data.size()) {
523 switch (m_method) {
525 channel_result.event_positions = Kinesis::Discrete::zero_crossing_positions(
526 original_data[ch], 0.0);
527 break;
528
529 case EnergyMethod::PEAK: {
530 double peak_threshold = m_classification_enabled ? m_quiet_threshold : 0.01;
531 channel_result.event_positions = Kinesis::Discrete::peak_positions(
532 original_data[ch], peak_threshold, m_hop_size / 4);
533 break;
534 }
535
541 default:
542 // event_positions remains empty
543 break;
544 }
545 }
546
548 channel_result.classifications.reserve(ch_energy.size());
549 channel_result.level_counts.fill(0);
550
551 for (double energy : ch_energy) {
552 EnergyLevel level = classify_energy_level(energy);
553 channel_result.classifications.push_back(level);
554 channel_result.level_counts[static_cast<size_t>(level)]++;
555 }
556 }
557 }
558
559 return result;
560 }
561
562 /**
563 * @brief Create pipeline output from input and energy values
564 */
566 {
567 std::vector<std::vector<double>> channel_energies;
568 channel_energies.reserve(analysis_result.channels.size());
569
570 for (const auto& ch : analysis_result.channels) {
571 channel_energies.push_back(ch.energy_values);
572 }
573
574 output_type output = this->convert_result(channel_energies, info);
575
576 output.metadata = input.metadata;
577
578 output.metadata["source_analyzer"] = "EnergyAnalyzer";
579 output.metadata["energy_method"] = method_to_string(analysis_result.method_used);
580 output.metadata["window_size"] = analysis_result.window_size;
581 output.metadata["hop_size"] = analysis_result.hop_size;
582 output.metadata["num_channels"] = analysis_result.channels.size();
583
584 if (!analysis_result.channels.empty()) {
585 std::vector<double> channel_means, channel_maxs, channel_mins, channel_variances;
586 std::vector<size_t> channel_window_counts;
587
588 for (const auto& ch : analysis_result.channels) {
589 channel_means.push_back(ch.mean_energy);
590 channel_maxs.push_back(ch.max_energy);
591 channel_mins.push_back(ch.min_energy);
592 channel_variances.push_back(ch.variance);
593 channel_window_counts.push_back(ch.energy_values.size());
594 }
595
596 output.metadata["mean_energy_per_channel"] = channel_means;
597 output.metadata["max_energy_per_channel"] = channel_maxs;
598 output.metadata["min_energy_per_channel"] = channel_mins;
599 output.metadata["variance_per_channel"] = channel_variances;
600 output.metadata["window_count_per_channel"] = channel_window_counts;
601 }
602
603 return output;
604 }
605
606 /**
607 * @brief Compute energy values using span (zero-copy processing)
608 */
609 [[nodiscard]] std::vector<double> compute_energy_values(std::span<const double> data, EnergyMethod method) const
610 {
611 namespace D = MayaFlux::Kinesis::Discrete;
612 const size_t num_windows = calculate_num_windows(data.size());
613
614 switch (method) {
616 return D::peak(data, num_windows, m_hop_size, m_window_size);
618 return D::zero_crossing_rate(data, num_windows, m_hop_size, m_window_size);
620 return D::power(data, num_windows, m_hop_size, m_window_size);
622 return D::dynamic_range(data, num_windows, m_hop_size, m_window_size);
624 return D::spectral_energy(data, num_windows, m_hop_size, m_window_size);
626 return D::low_frequency_energy(data, num_windows, m_hop_size, m_window_size);
628 default:
629 return D::rms(data, num_windows, m_hop_size, m_window_size);
630 }
631 }
632
633 /**
634 * @brief Calculate number of windows for given data size
635 */
636 [[nodiscard]] size_t calculate_num_windows(size_t data_size) const
637 {
638 if (data_size < m_window_size)
639 return 0;
640 return (data_size - m_window_size) / m_hop_size + 1;
641 }
642};
643
644/// Standard energy analyzer: DataVariant -> MatrixXd
646
647/// Container energy analyzer: SignalContainer -> MatrixXd
649
650/// Region energy analyzer: Region -> MatrixXd
652
653/// Raw energy analyzer: produces double vectors
654template <ComputeData InputType = std::vector<Kakshya::DataVariant>>
656
657/// Variant energy analyzer: produces DataVariant output
658template <ComputeData InputType = std::vector<Kakshya::DataVariant>>
660
661/**
662 * @brief Extract a named scalar from an EnergyAnalysis result.
663 *
664 * Maps qualifier strings to scalar fields of the first channel in @p analysis.
665 * All scalar-valued fields of ChannelEnergy are addressable.
666 *
667 * Supported qualifiers:
668 * - "mean_energy" mean energy across analysis windows
669 * - "max_energy" maximum window energy
670 * - "min_energy" minimum window energy
671 * - "variance" variance of window energy values
672 * - "dynamic_range" max_energy - min_energy
673 * - "event_count" number of detected energy events (peaks, zero crossings, etc.)
674 * - "window_count" number of analysis windows
675 *
676 * An empty qualifier resolves to "mean_energy".
677 * Unknown qualifiers fall back to mean_energy.
678 *
679 * @param analysis Result produced by EnergyAnalyzer.
680 * @param qualifier Name of the scalar to extract.
681 * @return Extracted double value, or 0.0 if channels is empty.
682 */
683[[nodiscard]] MAYAFLUX_API inline double extract_scalar_energy(
684 const EnergyAnalysis& analysis, const std::string& qualifier)
685{
686 if (analysis.channels.empty())
687 return 0.0;
688
689 const auto& ch = analysis.channels[0];
690 const std::string q = qualifier.empty() ? "mean_energy" : qualifier;
691
692 if (q == "mean_energy")
693 return ch.mean_energy;
694 if (q == "max_energy")
695 return ch.max_energy;
696 if (q == "min_energy")
697 return ch.min_energy;
698 if (q == "variance")
699 return ch.variance;
700 if (q == "dynamic_range")
701 return ch.max_energy - ch.min_energy;
702 if (q == "event_count")
703 return static_cast<double>(ch.event_positions.size());
704 if (q == "window_count")
705 return static_cast<double>(ch.energy_values.size());
706
707 return ch.mean_energy;
708}
709
710} // namespace MayaFlux::Yantra
Discrete sequence analysis primitives for MayaFlux::Kinesis.
#define MF_ERROR(comp, ctx,...)
Core::GlobalInputConfig input
Definition Config.cpp:42
bool size
size_t a
size_t b
double q
Modern, digital-first universal analyzer framework for Maya Flux.
glm::vec3 value
std::string name
Definition VKDevice.cpp:123
output_type convert_result(std::vector< std::vector< double > > &result_data, DataStructureInfo &metadata)
Convert processed double data back to OutputType using metadata and optional callback.
EnergyMethod get_energy_method() const
Get current energy computation method.
size_t calculate_num_windows(size_t data_size) const
Calculate number of windows for given data size.
bool supports_method(const std::string &method) const override
Check if a specific method is supported.
output_type create_pipeline_output(const input_type &input, const EnergyAnalysis &analysis_result, DataStructureInfo &info)
Create pipeline output from input and energy values.
static EnergyMethod string_to_method(const std::string &str)
Convert string to energy method enum.
void enable_classification(bool enabled)
Enable or disable energy level classification.
AnalysisType get_analysis_type() const override
Get analysis type category.
EnergyAnalyzer(const EnergyAnalyzerConfig &config)
Construct and configure an energy analyzer in one step.
EnergyAnalyzer(uint32_t window_size=256, uint32_t hop_size=128)
Construct EnergyAnalyzer with configurable window parameters.
EnergyAnalysis create_analysis_result(const std::vector< std::vector< double > > &energy_values, std::vector< std::span< const double > > original_data, const DataStructureInfo &) const
Create comprehensive analysis result from energy computation.
void set_energy_method(EnergyMethod method)
Set energy computation method.
std::any get_analysis_parameter(const std::string &name) const override
Get analysis-specific parameter.
int get_level_count(const ChannelEnergy &channel, EnergyLevel level)
Get count of windows in a specific energy level for a channel.
static std::string method_to_string(EnergyMethod method)
Convert energy method enum to string.
output_type analyze_implementation(const input_type &input) override
Core analysis implementation - creates analysis result AND pipeline output.
void set_energy_thresholds(double silent, double quiet, double moderate, double loud)
Set energy level classification thresholds.
std::vector< double > compute_energy_values(std::span< const double > data, EnergyMethod method) const
Compute energy values using span (zero-copy processing)
std::vector< std::string > get_available_methods() const override
Get available analysis methods.
EnergyAnalysis analyze_energy(const input_type &data)
Type-safe energy analysis method.
void set_window_parameters(uint32_t window_size, uint32_t hop_size)
Set window parameters for analysis.
static std::string energy_level_to_string(EnergyLevel level)
Convert energy level enum to string.
std::string get_analyzer_name() const override
Get analyzer name.
EnergyAnalysis analyze_energy(const InputType &data)
void set_analysis_parameter(const std::string &name, std::any value) override
Handle analysis-specific parameters.
EnergyLevel classify_energy_level(double energy) const
Classify energy value into qualitative level.
EnergyAnalysis get_energy_analysis() const
Get last energy analysis result (type-safe)
High-performance energy analyzer with zero-copy processing.
static std::tuple< std::vector< std::span< double > >, DataStructureInfo > extract_structured_double(T &compute_data)
Extract structured double data from Datum container or direct ComputeData with automatic container ha...
virtual void set_analysis_parameter(const std::string &name, std::any value)
Analysis-specific parameter handling (override for custom parameters)
std::any get_current_analysis() const
Access cached analysis from last operation.
void set_parameter(const std::string &name, std::any value) override
Type-safe parameter management with analysis-specific defaults.
std::any analyze_data(const input_type &data)
User-facing analysis method - returns analysis results directly.
virtual std::any get_analysis_parameter(const std::string &name) const
void store_current_analysis(AnalysisResultType &&result) const
void set_analysis_granularity(AnalysisGranularity granularity)
Template-flexible analyzer base with instance-defined I/O types.
@ ComputeMatrix
Compute operations (Yantra - algorithms, matrices, DSP)
@ Yantra
DSP algorithms, computational units, matrix operations, Grammar.
std::vector< double > low_frequency_energy(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size, double low_bin_fraction)
Low-frequency spectral energy per window.
Definition Analysis.cpp:164
std::vector< double > spectral_energy(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Spectral energy per window using Hann-windowed FFT.
Definition Analysis.cpp:133
std::vector< double > power(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Power (sum of squares) per window.
Definition Analysis.cpp:70
std::vector< size_t > zero_crossing_positions(std::span< const double > data, double threshold)
Sample indices of zero crossings in the full span.
Definition Analysis.cpp:634
std::vector< double > peak(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Peak amplitude per window.
Definition Analysis.cpp:51
std::vector< double > dynamic_range(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Dynamic range in dB per window.
Definition Analysis.cpp:89
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.
Definition Analysis.cpp:669
std::vector< double > zero_crossing_rate(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
Zero-crossing rate per window.
Definition Analysis.cpp:112
std::vector< double > rms(std::span< const double > data, size_t n_windows, uint32_t hop_size, uint32_t window_size)
RMS energy per window.
Definition Analysis.cpp:32
std::string enum_to_lowercase_string(EnumType value) noexcept
Universal enum to lowercase string converter using magic_enum.
AnalysisType
Categories of analysis operations for discovery and organization.
@ FEATURE
Feature extraction and characterization.
MAYAFLUX_API double extract_scalar_energy(const EnergyAnalysis &analysis, const std::string &qualifier)
Extract a named scalar from an EnergyAnalysis result.
EnergyMethod
Supported energy computation methods.
@ 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.
AnalysisGranularity
Output granularity control for analysis results.
@ RAW_VALUES
Direct analysis results.
std::vector< size_t > event_positions
std::vector< EnergyLevel > classifications
std::vector< std::pair< size_t, size_t > > window_positions
std::array< int, 5 > level_counts
std::vector< double > energy_values
Dimensions, modality, source type, and optional Composite field schema.
std::unordered_map< std::string, std::any > metadata
Associated metadata.
Definition DataIO.hpp:30
Input/Output container for computation pipeline data flow with structure preservation.
Definition DataIO.hpp:26
std::vector< ChannelEnergy > channels
Analysis result structure for energy analysis.
std::map< std::string, std::any > parameters
Additional named parameters applied last.
std::array< double, 4 > thresholds
Silent, quiet, moderate, and loud boundaries, in that order.
bool classification_enabled
Whether to classify energy levels.
uint32_t hop_size
Distance between successive windows in samples.
AnalysisGranularity granularity
Level at which the analyzer processes input.
EnergyMethod method
Energy calculation to perform.
uint32_t window_size
Analysis window length in samples.
Initial settings for energy analysis.