6uint64_t
coordinates_to_linear(
const std::vector<uint64_t>& coords,
const std::vector<DataDimension>& dimensions)
9 uint64_t multiplier = 1;
10 for (
int i = dimensions.size() - 1; i >= 0; --i) {
11 if (i < coords.size()) {
12 index += coords[i] * multiplier;
14 multiplier *= dimensions[i].size;
21 std::vector<uint64_t> coords(dimensions.size());
22 for (
int i = dimensions.size() - 1; i >= 0; --i) {
23 coords[i] = index % dimensions[i].size;
24 index /= dimensions[i].size;
31 std::vector<uint64_t> strides(dimensions.size());
33 for (
int i = dimensions.size() - 1; i >= 0; --i) {
35 stride *= dimensions[i].size;
46 for (
size_t i = 0; i < dimensions.size(); ++i) {
56 const std::vector<uint64_t>& slice_end,
57 const std::vector<DataDimension>& dimensions)
59 if (slice_start.size() != dimensions.size() || slice_end.size() != dimensions.size()) {
63 for (
size_t i = 0; i < dimensions.size(); ++i) {
64 if (slice_start[i] > slice_end[i] || slice_end[i] >= dimensions[i].size) {
73 const std::vector<DataDimension>& dimensions)
75 for (
size_t i = 0; i < coords.size() && i < dimensions.size(); ++i) {
76 coords[i] = std::min(coords[i], dimensions[i].size - 1);
81 const std::vector<double>& scale_factors,
82 const std::vector<int64_t>& offset_values,
83 const std::unordered_map<std::string, std::any>& rotation_params)
85 std::vector<uint64_t> transformed = coords;
87 if (!scale_factors.empty()) {
88 for (
size_t i = 0; i < coords.size() && i < scale_factors.size(); ++i) {
89 transformed[i] =
static_cast<uint64_t
>(scale_factors[i] *
static_cast<double>(coords[i]));
93 if (!offset_values.empty()) {
94 for (
size_t i = 0; i < transformed.size() && i < offset_values.size(); ++i) {
95 int64_t new_coord =
static_cast<int64_t
>(transformed[i]) + offset_values[i];
96 transformed[i] =
static_cast<uint64_t
>(std::max(int64_t(0), new_coord));
100 if (!rotation_params.empty() && coords.size() >= 2) {
101 auto angle_it = rotation_params.find(
"angle_radians");
102 if (angle_it != rotation_params.end()) {
104 auto angle = safe_any_cast_or_throw<double>(angle_it->second);
105 double cos_a = std::cos(angle);
106 double sin_a = std::sin(angle);
108 auto x =
static_cast<double>(transformed[0]);
109 auto y =
static_cast<double>(transformed[1]);
111 transformed[0] =
static_cast<uint64_t
>(x * cos_a - y * sin_a);
112 transformed[1] =
static_cast<uint64_t
>(x * sin_a + y * cos_a);
113 }
catch (
const std::bad_any_cast&) {
123 const std::vector<uint64_t>& positions,
124 const Region& loop_region,
125 bool looping_enabled)
136 if (loop_end_frame <= loop_start_frame) {
140 std::vector<uint64_t> wrapped_positions = positions;
141 uint64_t loop_length = loop_end_frame - loop_start_frame + 1;
143 for (
size_t ch = loop_start_channel; ch <= loop_end_channel && ch < positions.size(); ++ch) {
144 if (positions[ch] > loop_end_frame) {
145 uint64_t overflow = positions[ch] - loop_end_frame;
146 wrapped_positions[ch] = loop_start_frame + (overflow % loop_length);
150 return wrapped_positions;
154 const std::vector<uint64_t>& current_positions,
155 uint64_t frames_to_advance,
157 bool looping_enabled,
158 const Region& loop_region)
163 if (current_positions.size() != num_channels) {
164 throw std::invalid_argument(
165 "Position vector size " + std::to_string(current_positions.size()) +
" must match channel count " + std::to_string(num_channels));
168 std::vector<uint64_t> new_positions;
169 new_positions.reserve(num_channels);
171 for (
size_t ch = 0; ch < num_channels; ++ch) {
172 uint64_t current_frame = current_positions[ch];
173 uint64_t new_frame = current_frame + frames_to_advance;
175 if (new_frame >= total_frames) {
184 if (loop_end > loop_start) {
185 uint64_t loop_length = loop_end - loop_start + 1;
186 uint64_t overflow = new_frame - total_frames;
187 new_frame = loop_start + (overflow % loop_length);
189 new_frame = loop_start;
192 new_frame = total_frames - 1;
196 new_positions.push_back(new_frame);
199 return new_positions;
203 const std::vector<uint64_t>& current_positions,
204 const std::vector<uint64_t>& frames_per_channel,
206 bool looping_enabled,
207 const Region& loop_region)
212 if (current_positions.size() != num_channels || frames_per_channel.size() != num_channels) {
213 throw std::invalid_argument(
"All vectors must match channel count");
216 std::vector<uint64_t> new_positions;
217 new_positions.reserve(num_channels);
219 for (
size_t ch = 0; ch < num_channels; ++ch) {
220 uint64_t current_frame = current_positions[ch];
221 uint64_t frames_to_advance = frames_per_channel[ch];
222 uint64_t new_frame = current_frame + frames_to_advance;
224 if (new_frame >= total_frames) {
233 if (loop_end > loop_start) {
234 uint64_t loop_length = loop_end - loop_start + 1;
235 uint64_t overflow = new_frame - total_frames;
236 new_frame = loop_start + (overflow % loop_length);
238 new_frame = loop_start;
241 new_frame = total_frames - 1;
245 new_positions.push_back(new_frame);
248 return new_positions;
253 return static_cast<uint64_t
>(time * sample_rate);
258 return static_cast<double>(position) / sample_rate;
263 if (dimensions.empty() || primary_dim >= dimensions.size()) {
266 uint64_t frame_size = 1;
267 for (
size_t i = 0; i < dimensions.size(); ++i) {
268 if (i != primary_dim) {
269 frame_size *= dimensions[i].size;
278 throw std::invalid_argument(
"Container is null");
281 std::unordered_map<std::string, std::any> mapping_info;
282 const auto dimensions = container->get_dimensions();
284 std::vector<std::unordered_map<std::string, std::any>> dim_mappings;
285 dim_mappings.reserve(dimensions.size());
287 for (
size_t i = 0; i < dimensions.size(); ++i) {
288 std::unordered_map<std::string, std::any> dim_map;
289 dim_map[
"index"] = i;
290 dim_map[
"name"] = dimensions[i].name;
291 dim_map[
"size"] = dimensions[i].size;
292 dim_map[
"stride"] = dimensions[i].stride;
293 dim_map[
"role"] =
static_cast<int>(dimensions[i].role);
295 uint64_t offset = (i == 0) ? 0ULL : std::accumulate(dimensions.begin(), dimensions.begin() + i, 1ULL, [](uint64_t acc,
const auto& d) { return acc * d.size; });
296 dim_map[
"offset"] = offset;
298 dim_mappings.push_back(std::move(dim_map));
301 mapping_info[
"dimensions"] = std::move(dim_mappings);
302 mapping_info[
"total_elements"] = container->get_total_elements();
303 mapping_info[
"memory_layout"] =
static_cast<int>(container->get_memory_layout());
306 mapping_info[
"calculated_strides"] = strides;
313 std::vector<int> roles;
314 roles.reserve(dimensions.size());
316 for (
const auto& dim : dimensions) {
317 roles.push_back(
static_cast<int>(dim.role));
325 std::vector<uint64_t> sizes;
326 sizes.reserve(dimensions.size());
328 for (
const auto& dim : dimensions) {
329 sizes.push_back(dim.size);
335std::vector<std::unordered_map<std::string, std::any>>
create_dimension_info(
const std::vector<DataDimension>& dimensions)
337 std::vector<std::unordered_map<std::string, std::any>> dim_info;
338 dim_info.reserve(dimensions.size());
340 for (
const auto& dim : dimensions) {
341 std::unordered_map<std::string, std::any> info;
342 info[
"name"] = dim.name;
343 info[
"size"] = dim.size;
344 info[
"stride"] = dim.stride;
345 info[
"role"] =
static_cast<int>(dim.role);
346 dim_info.push_back(std::move(info));
353 const std::vector<uint64_t>& coords,
354 const std::vector<DataDimension>& dimensions)
356 size_t channel_dim_idx = 0;
357 size_t time_dim_idx = 0;
359 for (
size_t i = 0; i < dimensions.size(); ++i) {
367 return { coords[channel_dim_idx], coords[time_dim_idx] };
uint64_t coordinates_to_linear(const std::vector< uint64_t > &coords, const std::vector< DataDimension > &dimensions)
Convert N-dimensional coordinates to a linear index for interleaved data.
std::vector< std::unordered_map< std::string, std::any > > create_dimension_info(const std::vector< DataDimension > &dimensions)
Create structured dimension information.
void clamp_coordinates_to_bounds(std::vector< uint64_t > &coords, const std::vector< DataDimension > &dimensions)
Clamp coordinates to valid container bounds.
std::pair< size_t, uint64_t > coordinates_to_planar_indices(const std::vector< uint64_t > &coords, const std::vector< DataDimension > &dimensions)
Convert coordinates to planar indices (channel vector + frame index).
std::vector< int > extract_dimension_roles(const std::vector< DataDimension > &dimensions)
Extract dimension roles as integers.
bool validate_slice_bounds(const std::vector< uint64_t > &slice_start, const std::vector< uint64_t > &slice_end, const std::vector< DataDimension > &dimensions)
Validate slice coordinates against container bounds.
std::vector< uint64_t > advance_position(const std::vector< uint64_t > ¤t_positions, uint64_t frames_to_advance, const ContainerDataStructure &structure, bool looping_enabled, const Region &loop_region)
Advance current positions by a number of frames, with optional looping.
std::vector< uint64_t > calculate_strides(const std::vector< DataDimension > &dimensions)
Calculate memory strides for each dimension (row-major order).
std::vector< uint64_t > linear_to_coordinates(uint64_t index, const std::vector< DataDimension > &dimensions)
Convert a linear index to N-dimensional coordinates for interleaved data.
bool validate_region_bounds(const Region ®ion, const std::vector< DataDimension > &dimensions)
Validate region bounds against container dimensions.
double position_to_time(uint64_t position, double sample_rate)
Convert position (samples/frames) to time (seconds) given a sample rate.
uint64_t calculate_frame_size_for_dimension(const std::vector< DataDimension > &dimensions, size_t primary_dim)
Calculate the frame size for a specific primary dimension.
std::unordered_map< std::string, std::any > create_coordinate_mapping(const std::shared_ptr< SignalSourceContainer > &container)
Create coordinate mapping information for container.
std::vector< uint64_t > extract_dimension_sizes(const std::vector< DataDimension > &dimensions)
Extract dimension sizes.
uint64_t time_to_position(double time, double sample_rate)
Convert time (seconds) to position (samples/frames) given a sample rate.
std::vector< uint64_t > transform_coordinates(const std::vector< uint64_t > &coords, const std::vector< double > &scale_factors, const std::vector< int64_t > &offset_values, const std::unordered_map< std::string, std::any > &rotation_params)
Transform coordinates using scaling, translation, rotation.
std::vector< uint64_t > wrap_position_with_loop(const std::vector< uint64_t > &positions, const Region &loop_region, bool looping_enabled)
Wrap a position within loop boundaries if looping is enabled.
static uint64_t get_channel_count(const std::vector< DataDimension > &dimensions)
Extract channel count from dimensions.
static uint64_t get_samples_count_per_channel(const std::vector< DataDimension > &dimensions)
Get samples per channel (time dimension only).
Container structure for consistent dimension ordering.
@ TIME
Temporal progression (samples, frames, steps)
@ CHANNEL
Parallel streams (audio channels, color channels)
std::vector< uint64_t > end_coordinates
Ending frame index (inclusive)
std::vector< uint64_t > start_coordinates
Starting frame index (inclusive)
Represents a point or span in N-dimensional space.