Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
loop_segment_iterator.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <concepts>
7#include <vector>
8
9#include "dsp/tick_types.h"
10
11namespace zrythm::structure::arrangement
12{
13
25{
27 dsp::ContentTick virt_start;
29 dsp::ContentTick virt_end;
31 dsp::ContentTick abs_start;
33 dsp::ContentTick abs_end;
34};
35
55template <std::invocable<const LoopSegment &> Func>
56void
57for_each_loop_segment (
58 dsp::ContentTick clip_start,
59 dsp::ContentTick loop_start,
60 dsp::ContentTick loop_end,
61 dsp::ContentTick end_tick,
62 Func &&callback)
63{
64 const auto loop_length =
65 max (dsp::ContentTick{ units::ticks (0.0) }, loop_end - loop_start);
66
67 auto virt_start = clip_start;
68 auto virt_end = loop_end;
69 auto abs_start = dsp::ContentTick{ units::ticks (0.0) };
70 auto abs_end = loop_end - clip_start;
71
72 // Clamp first leg to end_tick.
73 if (abs_end > end_tick)
74 {
75 const auto diff = abs_end - end_tick;
76 virt_end = virt_end - diff;
77 abs_end = abs_end - diff;
78 }
79
80 while (abs_start < end_tick)
81 {
82 if (abs_end <= abs_start)
83 break;
84
85 callback (LoopSegment{ virt_start, virt_end, abs_start, abs_end });
86
87 const auto current_len = abs_end - abs_start;
88 if (current_len <= dsp::ContentTick{})
89 break;
90
91 // Subsequent legs use the loop region.
92 virt_start = loop_start;
93 virt_end = loop_end;
94 abs_start = abs_start + current_len;
95 abs_end = abs_end + loop_length;
96
97 if (abs_end > end_tick)
98 {
99 const auto diff = abs_end - end_tick;
100 virt_end = virt_end - diff;
101 abs_end = abs_end - diff;
102 }
103 }
104}
105
122template <typename WarpLookup>
123std::vector<dsp::TimelineTick>
124compute_loop_boundary_deltas (
125 WarpLookup &&warp_lookup,
126 dsp::ContentTick clip_start_ct,
127 dsp::ContentTick loop_start_ct,
128 dsp::ContentTick loop_end_ct,
129 dsp::TimelineTick max_delta_ticks,
130 int max_iterations = 1000)
131{
132 std::vector<dsp::TimelineTick> result;
133
134 const auto loop_length =
135 max (dsp::ContentTick{ units::ticks (0.0) }, loop_end_ct - loop_start_ct);
136 if (loop_length <= dsp::ContentTick{})
137 return result;
138
139 auto cumulative = loop_end_ct - clip_start_ct;
140
141 for (int i = 0; i < max_iterations; ++i)
142 {
143 const auto delta = warp_lookup (cumulative);
144 if (delta >= max_delta_ticks)
145 break;
146 result.push_back (delta);
147 cumulative = cumulative + loop_length;
148 }
149
150 return result;
151}
152
153} // namespace zrythm::structure::arrangement
float max(std::span< const float > buf)
Gets the maximum of the buffer.
One iteration of the loop-expanded clip content.
dsp::ContentTick virt_end
End of this segment's range in source-content space.
dsp::ContentTick abs_end
End of this segment in clip-absolute space.
dsp::ContentTick abs_start
Start of this segment in clip-absolute space (0 = clip start).
dsp::ContentTick virt_start
Start of this segment's range in source-content space.