MayaFlux 0.5.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
NDData.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <glm/glm.hpp>
4
5#include "typeindex"
6
7namespace MayaFlux::Kakshya {
8
9namespace detail {
10
11 template <typename V>
13
14 template <typename... Vecs>
15 struct span_const_from_vector_variant<std::variant<Vecs...>> {
16 using type = std::variant<std::span<const typename Vecs::value_type>...>;
17 };
18
19} // namespace detail
20
21/**
22 * @enum GpuDataFormat
23 * @brief GPU data formats with explicit precision levels
24 */
25enum class GpuDataFormat : uint8_t {
26 FLOAT32, // 32-bit float (standard GPU)
27 VEC2_F32, // glm::vec2 (32-bit components)
28 VEC3_F32, // glm::vec3 (32-bit components) — not a sampled image format
29 VEC4_F32, // glm::vec4 (32-bit components)
30
31 FLOAT64, // 64-bit double (audio precision)
32 VEC2_F64, // glm::dvec2 (64-bit components)
33 VEC3_F64, // glm::dvec3 (64-bit components)
34 VEC4_F64, // glm::dvec4 (64-bit components)
35
36 INT32,
37 UINT32,
38
39 UINT8, // uint8_t — R8 / RGBA8 texel data
40 UINT16, // uint16_t — R16F raw half-float storage, packed formats
41};
42
43/**
44 * @brief Byte size of one element of a GpuDataFormat.
45 *
46 * Single authoritative source for format sizing. Used by TextureAccess,
47 * ShaderSpec, and any other system that needs to derive byte counts from
48 * GpuDataFormat without duplicating the switch.
49 *
50 * @param fmt GpuDataFormat value.
51 * @return Byte size of one element, or 0 for unrecognised formats.
52 */
53MAYAFLUX_API size_t gpu_data_format_bytes(GpuDataFormat fmt) noexcept;
54
55/**
56 * @brief Memory layout for multi-dimensional data.
57 *
58 * Specifies how multi-dimensional data is mapped to linear memory.
59 * - ROW_MAJOR: Last dimension varies fastest (C/C++ style).
60 * - COLUMN_MAJOR: First dimension varies fastest (Fortran/MATLAB style).
61 *
62 * This abstraction enables flexible, efficient access patterns for
63 * digital-first, data-driven workflows, unconstrained by analog conventions.
64 */
65enum class MemoryLayout : uint8_t {
66 ROW_MAJOR, ///< C/C++ style (last dimension varies fastest)
67 COLUMN_MAJOR ///< Fortran/MATLAB style (first dimension varies fastest)
68};
69
70/**
71 * @brief Data organization strategy for multi-channel/multi-frame data.
72 *
73 * Determines how logical units (channels, frames) are stored in memory.
74 */
75enum class OrganizationStrategy : uint8_t {
76 INTERLEAVED, ///< Single DataVariant with interleaved data (LRLRLR for stereo)
77 PLANAR, ///< Separate DataVariant per logical unit (LLL...RRR for stereo)
78 HYBRID, ///< Mixed approach based on access patterns
79 USER_DEFINED ///< Custom organization
80};
81
82/**
83 * @brief Multi-type data storage for different precision needs.
84 *
85 * DataVariant enables containers to store and expose data in the most
86 * appropriate format for the application, supporting high-precision,
87 * standard-precision, integer, and complex types. This abstraction
88 * is essential for digital-first, data-driven processing pipelines.
89 */
90using DataVariant = std::variant<
91 std::vector<double>, ///< High precision floating point
92 std::vector<float>, ///< Standard precision floating point
93 std::vector<uint8_t>, ///< 8-bit data (images, compressed audio)
94 std::vector<uint16_t>, ///< 16-bit data (CD audio, images)
95 std::vector<uint32_t>, ///< 32-bit data (high precision int)
96 std::vector<std::complex<float>>, ///< Complex data (spectral)
97 std::vector<std::complex<double>>, ///< High precision complex
98 std::vector<glm::vec2>, ///< 2D vector data
99 std::vector<glm::vec3>, ///< 3D vector data
100 std::vector<glm::vec4>, ///< 4D vector data
101 std::vector<glm::mat4> ///< 4x4 matrix data
102 >;
103
104/**
105 * @brief Type traits to determine if a type is a valid DataVariant element.
106 *
107 * This trait is used to constrain template functions that operate on DataVariant types,
108 * ensuring that only supported data types are used in the context of NDData containers.
109 */
110template <typename T>
111struct is_data_variant_element : std::false_type { };
112
113/** high precision floating point data (double) (audio) */
114template <>
115struct is_data_variant_element<double> : std::true_type { };
116
117/** standard precision floating point data (float) (params) */
118template <>
119struct is_data_variant_element<float> : std::true_type { };
120
121/** 8-bit unsigned integer data (uint8_t) (images, compressed audio) */
122template <>
123struct is_data_variant_element<uint8_t> : std::true_type { };
124
125/** 16-bit unsigned integer data (uint16_t) (CD audio, images) */
126template <>
127struct is_data_variant_element<uint16_t> : std::true_type { };
128
129/** 32-bit unsigned integer data (uint32_t) (high precision int) */
130template <>
131struct is_data_variant_element<uint32_t> : std::true_type { };
132
133/** complex data (spectral) */
134template <>
135struct is_data_variant_element<std::complex<float>> : std::true_type { };
136
137/** high precision complex data (spectral) */
138template <>
139struct is_data_variant_element<std::complex<double>> : std::true_type { };
140
141/** 2D vector data (glm::vec2) */
142template <>
143struct is_data_variant_element<glm::vec2> : std::true_type { };
144
145/** 3D vector data (glm::vec3) */
146template <>
147struct is_data_variant_element<glm::vec3> : std::true_type { };
148
149/** 4D vector data (glm::vec4) */
150template <>
151struct is_data_variant_element<glm::vec4> : std::true_type { };
152
153/** 4x4 matrix data (glm::mat4) */
154template <>
155struct is_data_variant_element<glm::mat4> : std::true_type { };
156
157/** Concept to constrain types to valid DataVariant elements */
158template <typename T>
159concept DataVariantElement = is_data_variant_element<std::remove_cvref_t<T>>::value;
160
161/**
162 * @brief Data modality types for cross-modal analysis
163 */
164enum class DataModality : uint8_t {
165 AUDIO_1D, ///< 1D audio signal
166 AUDIO_MULTICHANNEL, ///< Multi-channel audio
167 IMAGE_2D, ///< 2D image (grayscale or single channel)
168 IMAGE_COLOR, ///< 2D RGB/RGBA image
169 IMAGE_COLOR_ARRAY, ///< 4D (idx + 2D + color)
170 DEPTH_MAP, ///< [height, width, components] - range/disparity image
171 VIDEO_GRAYSCALE, ///< 3D video (time + 2D grayscale)
172 VIDEO_COLOR, ///< 4D video (time + 2D + color)
173 VIDEO_DEPTH, ///< [frames, height, width, components] - streaming range data
174 TEXTURE_2D, ///< 2D texture data
175 TENSOR_ND, ///< N-dimensional tensor
176 SPECTRAL_2D, ///< 2D spectral data (time + frequency)
177 VOLUMETRIC_3D, ///< 3D volumetric data
178 VERTICES_3D, ///< 3D vertex data (positions, normals, etc.)
179 VERTEX_POSITIONS_3D, // glm::vec3 - vertex positions
180 VERTEX_NORMALS_3D, // glm::vec3 - vertex normals
181 VERTEX_TANGENTS_3D, // glm::vec3 - tangent vectors
182 VERTEX_COLORS_RGB, // glm::vec3 - RGB colors
183 VERTEX_COLORS_RGBA, // glm::vec4 - RGBA colors
184 TEXTURE_COORDS_2D, // glm::vec2 - UV coordinates
185 TRANSFORMATION_MATRIX, // glm::mat4 - transform matrices
186 SCALAR_F32, ///< Single-channel float data
187 UNKNOWN ///< Unknown or undefined modality
188};
189
190/**
191 * @brief Convert DataModality enum to string representation.
192 * @param modality DataModality value
193 * @return String view of the modality name
194 */
195std::string_view modality_to_string(DataModality modality);
196
197/**
198 * @brief Check if a modality represents structured data (vectors, matrices).
199 * @param modality DataModality value
200 * @return True if structured, false otherwise
201 */
203{
204 switch (modality) {
212 return true;
213 default:
214 return false;
215 }
216}
217
218/**
219 * @brief Minimal dimension descriptor focusing on structure only.
220 *
221 * DataDimension describes a single axis of an N-dimensional dataset,
222 * providing semantic hints (such as TIME, CHANNEL, SPATIAL_X, etc.)
223 * and structural information (name, size, stride).
224 *
225 * This abstraction enables containers to describe arbitrary data
226 * organizations, supporting digital-first, data-driven processing
227 * without imposing analog metaphors (e.g., "track", "tape", etc.).
228 */
229struct MAYAFLUX_API DataDimension {
230 /**
231 * @brief Semantic role of the dimension.
232 *
233 * Used to indicate the intended interpretation of the dimension,
234 * enabling generic algorithms to adapt to data structure.
235 */
236 enum class Role : uint8_t {
237 TIME, ///< Temporal progression (samples, frames, steps)
238 CHANNEL, ///< Parallel streams (audio channels, color channels)
239 SPATIAL_X, ///< Spatial X axis (images, tensors)
240 SPATIAL_Y, ///< Spatial Y axis
241 SPATIAL_Z, ///< Spatial Z axis
242 FREQUENCY, ///< Spectral/frequency axis
243 POSITION, ///< Vertex positions (3D space)
244 NORMAL, ///< Surface normals
245 TANGENT, ///< Tangent vectors
246 BITANGENT, ///< Bitangent vectors
247 UV, ///< Texture coordinates
248 COLOR, ///< Color data (RGB/RGBA)
249 DEPTH, ///< Distance from the observation point (depth, disparity, range)
250 INDEX, ///< Index buffer data
251 MIP_LEVEL, ///< Mipmap levels
252 CUSTOM ///< User-defined or application-specific
253 };
254
255 /**
256 * @brief Grouping information for sub-dimensions.
257 *
258 * Used to indicate that this dimension is composed of groups
259 * of sub-dimensions (e.g., color channels grouped per pixel).
260 */
262 uint8_t count;
263 uint8_t offset;
264
266 : count(0)
267 , offset(0)
268 {
269 }
270 ComponentGroup(uint8_t c, uint8_t o = 0)
271 : count(c)
272 , offset(o)
273 {
274 }
275 };
276
277 std::optional<ComponentGroup> grouping;
278
279 /**
280 * @brief Numeric interpretation of the values along this dimension.
281 *
282 * Size and stride describe how many numbers there are and where they sit.
283 * This describes what they mean: the span that maps onto [0, 1] under
284 * normalisation, and the raw value marking an absent reading.
285 *
286 * Absent for dimensions whose values are already normalised or whose
287 * range is implied by the storage type.
288 */
289 struct ValueRange {
290 double min {};
291 double max {};
292 std::optional<double> invalid;
293 };
294
295 std::optional<ValueRange> value_range;
296
297 std::string name; ///< Human-readable identifier for the dimension
298 uint64_t size {}; ///< Number of elements in this dimension
299 uint64_t stride {}; ///< Memory stride (elements between consecutive indices)
300 Role role = Role::CUSTOM; ///< Semantic hint for common operations
301
302 DataDimension() = default;
303
304 /**
305 * @brief Construct a dimension descriptor.
306 * @param n Name of the dimension
307 * @param s Size (number of elements)
308 * @param st Stride (default: 1)
309 * @param r Semantic role (default: CUSTOM)
310 */
311 DataDimension(std::string n, uint64_t s, uint64_t st = 1, Role r = Role::CUSTOM);
312
313 /**
314 * @brief Convenience constructor for a temporal (time) dimension.
315 * @param samples Number of samples/frames
316 * @param name Optional name (default: "time")
317 * @return DataDimension representing time
318 */
319 static DataDimension time(uint64_t samples, std::string name = "time");
320
321 /**
322 * @brief Convenience constructor for a channel dimension.
323 * @param count Number of channels
324 * @param stride Memory stride (default: 1)
325 * @return DataDimension representing channels
326 */
327 static DataDimension channel(uint64_t count, uint64_t stride = 1);
328
329 /**
330 * @brief Convenience constructor for a depth dimension.
331 *
332 * The component axis of a range image. Size is the number of values per
333 * pixel: 1 for plain depth, 2 for depth paired with confidence.
334 *
335 * Carries no numeric interpretation by itself. Chain with_range() to
336 * declare the span and invalid marker, since raw depth is rarely in [0, 1].
337 *
338 * @param count Components per pixel.
339 * @param stride Memory stride (default: 1).
340 * @return DataDimension representing depth components.
341 */
342 static DataDimension depth(uint64_t count = 1, uint64_t stride = 1);
343
344 /**
345 * @brief Convenience constructor for a frequency dimension.
346 * @param bins Number of frequency bins
347 * @param name Optional name (default: "frequency")
348 * @return DataDimension representing frequency
349 */
350 static DataDimension frequency(uint64_t bins, std::string name = "frequency");
351
352 /**
353 * @brief Convenience constructor for a spatial dimension.
354 * @param size Number of elements along this axis
355 * @param axis Axis character ('x', 'y', or 'z')
356 * @param stride Memory stride (default: 1)
357 * @param name Optional name (default: "pixels")
358 * @return DataDimension representing a spatial axis
359 */
360 static DataDimension spatial(uint64_t size, char axis, uint64_t stride = 1, std::string name = "spatial");
361
362 /**
363 * @brief Convenience constructor for an array dimension.
364 * @param count Number of array elements
365 * @param name Optional name (default: "array")
366 * @return DataDimension representing an array
367 */
368 static DataDimension spatial_1d(uint64_t width);
369
370 /**
371 * @brief Convenience constructor for a 2D spatial dimension.
372 * @param width Width in elements
373 * @param height Height in elements
374 * @return DataDimension representing 2D spatial data
375 */
376 static DataDimension spatial_2d(uint64_t width, uint64_t height);
377
378 /**
379 * @brief Convenience constructor for a 3D spatial dimension.
380 * @param width Width in elements
381 * @param height Height in elements
382 * @param depth Depth in elements
383 * @return DataDimension representing 3D spatial data
384 */
385 static DataDimension spatial_3d(uint64_t width, uint64_t height, uint64_t depth);
386
387 /**
388 * @brief Create dimension with component grouping
389 * @param name Dimension name
390 * @param element_count Number of elements (not components)
391 * @param components_per_element Components per element (e.g., 3 for vec3)
392 * @param role Semantic role
393 */
394 static DataDimension grouped(std::string name, uint64_t element_count, uint8_t components_per_element, Role role = Role::CUSTOM);
395
396 /**
397 * @brief Attach a value range. Chainable.
398 * @param min Value mapping to 0.0.
399 * @param max Value mapping to 1.0. Must exceed min.
400 * @param invalid Raw value marking an absent reading.
401 */
402 DataDimension& with_range(double min, double max, std::optional<double> invalid = std::nullopt);
403
404 /**
405 * @brief Create dimension for vertex positions (vec3)
406 */
407 static DataDimension vertex_positions(uint64_t count);
408
409 /**
410 * @brief Create dimension for vertex normals (vec3)
411 */
412 static DataDimension vertex_normals(uint64_t count);
413
414 /**
415 * @brief Create dimension for texture coordinates (vec2)
416 */
417 static DataDimension texture_coords(uint64_t count);
418
419 /**
420 * @brief Create dimension for colors (vec3 or vec4)
421 */
422 static DataDimension vertex_colors(uint64_t count, bool has_alpha = false);
423
424 /**
425 * @brief Create dimension for mipmap levels.
426 */
427 static DataDimension mipmap_levels(uint64_t levels);
428
429 /**
430 * @brief Data container combining variants and dimensions.
431 */
432 using DataModule = std::pair<std::vector<DataVariant>, std::vector<DataDimension>>;
433
434 /**
435 * @brief Create data module for a specific modality.
436 * @tparam T Data type for storage
437 * @param modality Target data modality
438 * @param shape Dimensional sizes
439 * @param default_value Initial value for elements
440 * @param layout Memory layout strategy
441 * @param strategy Organization strategy
442 * @return DataModule with appropriate structure
443 */
444 template <typename T>
446 DataModality modality,
447 const std::vector<uint64_t>& shape,
448 T default_value = T {},
449 MemoryLayout layout = MemoryLayout::ROW_MAJOR,
450 OrganizationStrategy strategy = OrganizationStrategy::PLANAR)
451 {
452 auto dims = create_dimensions(modality, shape, layout);
453 auto variants = create_variants(modality, shape, default_value, strategy);
454
455 return { std::move(variants), std::move(dims) };
456 }
457
458 /**
459 * @brief Create dimension descriptors for a data modality.
460 * @param modality Target data modality
461 * @param shape Dimensional sizes
462 * @param layout Memory layout strategy
463 * @return Vector of DataDimension objects
464 */
465 static std::vector<DataDimension> create_dimensions(
466 DataModality modality,
467 const std::vector<uint64_t>& shape,
468 MemoryLayout layout = MemoryLayout::ROW_MAJOR);
469
470 /**
471 * @brief Create 1D audio data module.
472 * @tparam T Data type for storage
473 * @param samples Number of audio samples
474 * @param default_value Initial value for elements
475 * @return DataModule for 1D audio
476 */
477 template <typename T>
478 static DataModule create_audio_1d(uint64_t samples, T default_value = T {})
479 {
480 return create_for_modality(DataModality::AUDIO_1D, { samples }, default_value);
481 }
482
483 /**
484 * @brief Create multi-channel audio data module.
485 * @tparam T Data type for storage
486 * @param samples Number of audio samples
487 * @param channels Number of audio channels
488 * @param default_value Initial value for elements
489 * @return DataModule for multi-channel audio
490 */
491 template <typename T>
492 static DataModule create_audio_multichannel(uint64_t samples, uint64_t channels, T default_value = T {})
493 {
494 return create_for_modality(DataModality::AUDIO_MULTICHANNEL, { samples, channels }, default_value);
495 }
496
497 /**
498 * @brief Create 2D image data module.
499 * @tparam T Data type for storage
500 * @param height Image height in pixels
501 * @param width Image width in pixels
502 * @param default_value Initial value for elements
503 * @return DataModule for 2D image
504 */
505 template <typename T>
506 static DataModule create_image_2d(uint64_t height, uint64_t width, T default_value = T {})
507 {
508 return create_for_modality(DataModality::IMAGE_2D, { height, width }, default_value);
509 }
510
511 /**
512 * @brief Create 2D spectral data module.
513 * @tparam T Data type for storage
514 * @param time_windows Number of time windows
515 * @param frequency_bins Number of frequency bins
516 * @param default_value Initial value for elements
517 * @return DataModule for spectral data
518 */
519 template <typename T>
520 static DataModule create_spectral_2d(uint64_t time_windows, uint64_t frequency_bins, T default_value = T {})
521 {
522 return create_for_modality(DataModality::SPECTRAL_2D, { time_windows, frequency_bins }, default_value);
523 }
524
525 /**
526 * @brief Calculate memory strides based on shape and layout.
527 * @param shape Dimensional sizes
528 * @param layout Memory layout strategy
529 * @return Vector of stride values for each dimension
530 */
531 static std::vector<uint64_t> calculate_strides(
532 const std::vector<uint64_t>& shape,
533 MemoryLayout layout);
534
535private:
536 /**
537 * @brief Create data variants for a specific modality.
538 * @tparam T Data type for storage
539 * @param modality Target data modality
540 * @param shape Dimensional sizes
541 * @param default_value Initial value for elements
542 * @param org Organization strategy
543 * @return Vector of DataVariant objects
544 */
545 template <typename T>
546 static std::vector<DataVariant> create_variants(
547 DataModality modality,
548 const std::vector<uint64_t>& shape,
549 T default_value,
550 OrganizationStrategy org = OrganizationStrategy::PLANAR)
551 {
552 std::vector<DataVariant> variants;
553
554 if (org == OrganizationStrategy::INTERLEAVED) {
555 uint64_t total = std::accumulate(shape.begin(), shape.end(), uint64_t(1), std::multiplies<>());
556 variants.emplace_back(std::vector<T>(total, default_value));
557 return variants;
558 }
559
560 switch (modality) {
561 case DataModality::AUDIO_1D:
562 variants.emplace_back(std::vector<T>(shape[0], default_value));
563 break;
564
565 case DataModality::AUDIO_MULTICHANNEL: {
566 uint64_t samples = shape[0];
567 uint64_t channels = shape[1];
568 variants.reserve(channels);
569 for (uint64_t ch = 0; ch < channels; ++ch) {
570 variants.emplace_back(std::vector<T>(samples, default_value));
571 }
572 break;
573 }
574
575 case DataModality::IMAGE_2D:
576 variants.emplace_back(std::vector<T>(shape[0] * shape[1], default_value));
577 break;
578
579 case DataModality::IMAGE_COLOR: {
580 uint64_t height = shape[0];
581 uint64_t width = shape[1];
582 uint64_t channels = shape[2];
583 uint64_t pixels = height * width;
584 variants.reserve(channels);
585 for (uint64_t ch = 0; ch < channels; ++ch) {
586 variants.emplace_back(std::vector<T>(pixels, default_value));
587 }
588 break;
589 }
590
591 case DataModality::DEPTH_MAP: {
592 uint64_t pixels = shape[0] * shape[1];
593 uint64_t components = shape[2];
594 variants.reserve(components);
595 for (uint64_t c = 0; c < components; ++c) {
596 variants.emplace_back(std::vector<T>(pixels, default_value));
597 }
598 break;
599 }
600
601 case DataModality::SPECTRAL_2D:
602 variants.emplace_back(std::vector<T>(shape[0] * shape[1], default_value));
603 break;
604
605 case DataModality::VOLUMETRIC_3D:
606 variants.emplace_back(std::vector<T>(shape[0] * shape[1] * shape[2], default_value));
607 break;
608
609 case DataModality::VIDEO_GRAYSCALE: {
610 uint64_t frames = shape[0];
611 uint64_t height = shape[1];
612 uint64_t width = shape[2];
613 uint64_t frame_size = height * width;
614 variants.reserve(frames);
615 for (uint64_t f = 0; f < frames; ++f) {
616 variants.emplace_back(std::vector<T>(frame_size, default_value));
617 }
618 break;
619 }
620
621 case DataModality::VIDEO_COLOR: {
622 uint64_t frames = shape[0];
623 uint64_t height = shape[1];
624 uint64_t width = shape[2];
625 uint64_t channels = shape[3];
626 uint64_t frame_size = height * width;
627 variants.reserve(frames * channels);
628 for (uint64_t f = 0; f < frames; ++f) {
629 for (uint64_t ch = 0; ch < channels; ++ch) {
630 variants.emplace_back(std::vector<T>(frame_size, default_value));
631 }
632 }
633 break;
634 }
635
636 case DataModality::VIDEO_DEPTH: {
637 uint64_t frames = shape[0];
638 uint64_t pixels = shape[1] * shape[2];
639 uint64_t components = shape[3];
640 variants.reserve(components);
641 for (uint64_t c = 0; c < components; ++c) {
642 variants.emplace_back(std::vector<T>(frames * pixels, default_value));
643 }
644 break;
645 }
646
647 default:
648 uint64_t total = std::accumulate(shape.begin(), shape.end(), uint64_t(1), std::multiplies<>());
649 variants.emplace_back(std::vector<T>(total, default_value));
650 break;
651 }
652
653 return variants;
654 }
655};
656
658
659/**
660 * @class FrameView
661 * @brief Zero-copy typed view over one frame of container storage.
662 *
663 * FrameView is the return type of NDDataContainer::get_frame(). It holds a
664 * DataSpanVariant — a span into the container's live storage — without copying
665 * or converting data. The active span alternative matches the container's native
666 * element type: uint8_t for 8-bit image and video, uint16_t for 16-bit image,
667 * float for HDR image, double for audio.
668 *
669 * Callers retrieve typed data via as(), which returns an empty span on type
670 * mismatch rather than throwing. element_type() provides a runtime query for
671 * callers whose branch depends on the native type.
672 *
673 * @par Lifetime
674 * The span inside FrameView points directly into the owning container's internal
675 * buffer. It is valid only for the duration of the current processing turn.
676 * FrameView must not be stored across buffer cycles, frame callbacks, or any
677 * point at which the container may write new data.
678 *
679 * @par Threading
680 * FrameView is not thread-safe. The container's read lock (if any) is held only
681 * during get_frame_span_impl(); it is released before FrameView is returned.
682 * Callers must not access the view concurrently with container writes.
683 *
684 * @see NDDataContainer::get_frame(), DataSpanVariant, DataVariantElement
685 */
687public:
688 /** @brief Construct an empty FrameView. empty() returns true. */
689 FrameView() = default;
690
691 /**
692 * @brief Construct from a DataSpanVariant produced by get_frame_span_impl().
693 * @param span Active alternative must match the container's native element type.
694 */
696 : m_span(span)
697 {
698 }
699
700 /** @brief Returns true if the view holds no elements. */
701 [[nodiscard]] bool empty() const
702 {
703 return std::visit([](const auto& s) { return s.empty(); }, m_span);
704 }
705
706 /** @brief Number of elements in the frame, in units of the native element type. */
707 [[nodiscard]] size_t size() const
708 {
709 return std::visit([](const auto& s) { return s.size(); }, m_span);
710 }
711
712 /**
713 * @brief Runtime query for the native element type of this frame.
714 *
715 * Returns std::type_index of the active span's value_type. Typical values:
716 * - typeid(uint8_t) — 8-bit image/video (RGBA, etc.)
717 * - typeid(uint16_t) — 16-bit image (UNORM or half-float encoded)
718 * - typeid(float) — HDR image (R32F/RGBA32F)
719 * - typeid(double) — audio
720 *
721 * Use this to branch once before calling as<T>() when the container type
722 * is not statically known at the call site.
723 */
724 [[nodiscard]] std::type_index element_type() const
725 {
726 return std::visit([](const auto& s) {
727 return std::type_index(typeid(typename std::decay_t<decltype(s)>::value_type));
728 },
729 m_span);
730 }
731
732 /**
733 * @brief Return a typed span over the frame data without conversion.
734 *
735 * Returns an empty span if T does not match the native element type.
736 * Callers should query element_type() first when the type is not statically known.
737 * The returned span is valid only for the lifetime of the owning container's frame buffer.
738 *
739 * @tparam T Element type. Must satisfy DataVariantElement.
740 * @return Span of const T, empty on type mismatch.
741 */
742 /**
743 * @brief Return a typed span over the frame data without conversion or allocation.
744 *
745 * Returns an empty span if T does not match the native element type.
746 * No exception is thrown on mismatch; check empty() or call element_type() first
747 * when the container type is not statically known.
748 *
749 * The returned span aliases the container's internal buffer directly.
750 * See class-level lifetime and threading notes.
751 *
752 * @tparam T Element type. Must satisfy DataVariantElement.
753 * @return Span of const T into live storage, empty on type mismatch.
754 */
755 template <DataVariantElement T>
756 [[nodiscard]] std::span<const T> as() const
757 {
758 const auto* s = std::get_if<std::span<const T>>(&m_span);
759 return s ? *s : std::span<const T> {};
760 }
761
762 /**
763 * @brief Direct access to the underlying DataSpanVariant for internal use.
764 *
765 * Intended for infrastructure (processors, Yantra pipeline) that must
766 * forward the view without branching on type. Not for general callers.
767 */
768 [[nodiscard]] const DataSpanVariant& raw() const { return m_span; }
769
770private:
772};
773
774} // namespace MayaFlux::Kakshya
const std::vector< float > * pixels
Definition Decoder.cpp:65
double frequency
std::string name
Definition VKDevice.cpp:143
size_t count
float value
float offset
uint32_t width
uint32_t height
uint32_t depth
FrameView()=default
Construct an empty FrameView.
const DataSpanVariant & raw() const
Direct access to the underlying DataSpanVariant for internal use.
Definition NDData.hpp:768
std::span< const T > as() const
Return a typed span over the frame data without conversion.
Definition NDData.hpp:756
size_t size() const
Number of elements in the frame, in units of the native element type.
Definition NDData.hpp:707
std::type_index element_type() const
Runtime query for the native element type of this frame.
Definition NDData.hpp:724
FrameView(DataSpanVariant span)
Construct from a DataSpanVariant produced by get_frame_span_impl().
Definition NDData.hpp:695
bool empty() const
Returns true if the view holds no elements.
Definition NDData.hpp:701
Zero-copy typed view over one frame of container storage.
Definition NDData.hpp:686
Concept to constrain types to valid DataVariant elements.
Definition NDData.hpp:159
size_t gpu_data_format_bytes(GpuDataFormat fmt) noexcept
Byte size of one element of a GpuDataFormat.
Definition NDData.cpp:9
typename detail::span_const_from_vector_variant< DataVariant >::type DataSpanVariant
Definition NDData.hpp:657
std::variant< std::vector< double >, std::vector< float >, std::vector< uint8_t >, std::vector< uint16_t >, std::vector< uint32_t >, std::vector< std::complex< float > >, std::vector< std::complex< double > >, std::vector< glm::vec2 >, std::vector< glm::vec3 >, std::vector< glm::vec4 >, std::vector< glm::mat4 > > DataVariant
Multi-type data storage for different precision needs.
Definition NDData.hpp:102
DataModality
Data modality types for cross-modal analysis.
Definition NDData.hpp:164
@ DEPTH_MAP
[height, width, components] - range/disparity image
@ AUDIO_MULTICHANNEL
Multi-channel audio.
@ SPECTRAL_2D
2D spectral data (time + frequency)
@ VIDEO_DEPTH
[frames, height, width, components] - streaming range data
@ UNKNOWN
Unknown or undefined modality.
@ IMAGE_COLOR_ARRAY
4D (idx + 2D + color)
@ VERTICES_3D
3D vertex data (positions, normals, etc.)
@ SCALAR_F32
Single-channel float data.
@ VOLUMETRIC_3D
3D volumetric data
@ VIDEO_GRAYSCALE
3D video (time + 2D grayscale)
@ VIDEO_COLOR
4D video (time + 2D + color)
@ TENSOR_ND
N-dimensional tensor.
@ IMAGE_COLOR
2D RGB/RGBA image
@ IMAGE_2D
2D image (grayscale or single channel)
MemoryLayout
Memory layout for multi-dimensional data.
Definition NDData.hpp:65
@ ROW_MAJOR
C/C++ style (last dimension varies fastest)
@ COLUMN_MAJOR
Fortran/MATLAB style (first dimension varies fastest)
OrganizationStrategy
Data organization strategy for multi-channel/multi-frame data.
Definition NDData.hpp:75
@ HYBRID
Mixed approach based on access patterns.
@ PLANAR
Separate DataVariant per logical unit (LLL...RRR for stereo)
@ INTERLEAVED
Single DataVariant with interleaved data (LRLRLR for stereo)
bool is_structured_modality(DataModality modality)
Check if a modality represents structured data (vectors, matrices).
Definition NDData.hpp:202
GpuDataFormat
GPU data formats with explicit precision levels.
Definition NDData.hpp:25
std::string_view modality_to_string(DataModality modality)
Convert DataModality enum to string representation.
Definition NDData.cpp:130
Grouping information for sub-dimensions.
Definition NDData.hpp:261
Numeric interpretation of the values along this dimension.
Definition NDData.hpp:289
static DataModule create_audio_multichannel(uint64_t samples, uint64_t channels, T default_value=T {})
Create multi-channel audio data module.
Definition NDData.hpp:492
std::optional< ValueRange > value_range
Definition NDData.hpp:295
Role
Semantic role of the dimension.
Definition NDData.hpp:236
static DataModule create_spectral_2d(uint64_t time_windows, uint64_t frequency_bins, T default_value=T {})
Create 2D spectral data module.
Definition NDData.hpp:520
std::string name
Human-readable identifier for the dimension.
Definition NDData.hpp:297
static DataModule create_audio_1d(uint64_t samples, T default_value=T {})
Create 1D audio data module.
Definition NDData.hpp:478
static DataModule create_image_2d(uint64_t height, uint64_t width, T default_value=T {})
Create 2D image data module.
Definition NDData.hpp:506
std::pair< std::vector< DataVariant >, std::vector< DataDimension > > DataModule
Data container combining variants and dimensions.
Definition NDData.hpp:432
static std::vector< DataVariant > create_variants(DataModality modality, const std::vector< uint64_t > &shape, T default_value, OrganizationStrategy org=OrganizationStrategy::PLANAR)
Create data variants for a specific modality.
Definition NDData.hpp:546
static DataModule create_for_modality(DataModality modality, const std::vector< uint64_t > &shape, T default_value=T {}, MemoryLayout layout=MemoryLayout::ROW_MAJOR, OrganizationStrategy strategy=OrganizationStrategy::PLANAR)
Create data module for a specific modality.
Definition NDData.hpp:445
std::optional< ComponentGroup > grouping
Definition NDData.hpp:277
Minimal dimension descriptor focusing on structure only.
Definition NDData.hpp:229
std::variant< std::span< const typename Vecs::value_type >... > type
Definition NDData.hpp:16
Type traits to determine if a type is a valid DataVariant element.
Definition NDData.hpp:111