Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
region_renderer.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "structure/arrangement/arranger_object_all.h"
7#include "utils/units.h"
8
9#include <juce_wrapper.h>
10
11namespace zrythm::structure::arrangement
12{
13
20class RegionRenderer final
21{
22public:
37 const MidiRegion &region,
38 juce::MidiMessageSequence &events,
39 std::optional<std::pair<double, double>> timeline_range_ticks = std::nullopt);
40
55 const ChordRegion &region,
56 juce::MidiMessageSequence &events,
57 std::optional<std::pair<double, double>> timeline_range_ticks = std::nullopt);
58
72 static void serialize_to_buffer (
73 const AudioRegion &region,
74 juce::AudioSampleBuffer &buffer,
75 std::optional<std::pair<double, double>> timeline_range_ticks = std::nullopt);
76
108 const AutomationRegion &region,
109 std::vector<float> &values,
110 std::optional<std::pair<double, double>> timeline_range_ticks = std::nullopt)
111 [[clang::blocking]];
112
113private:
117 struct LoopParameters
118 {
119 units::precise_tick_t loop_start;
120 units::precise_tick_t loop_end;
121 units::precise_tick_t clip_start;
122 units::precise_tick_t loop_length;
123 units::precise_tick_t region_length;
124 int num_loops;
125
126 LoopParameters (const ArrangerObject &region);
127 };
128
129 template <RegionObject RegionT, typename EventsT>
130 static void serialize_region (
131 const RegionT &region,
132 EventsT &events,
133 // currently unused
134 std::optional<std::pair<double, double>> timeline_range_ticks = std::nullopt)
135 {
136 const auto * loop_range = region.loopRange ();
137 const auto loop_length = loop_range->get_loop_length_in_ticks ();
138 const auto region_length =
139 units::ticks (region.bounds ()->length ()->ticks ());
140
141 auto loop_segment_virtual_start =
142 units::ticks (loop_range->clipStartPosition ()->ticks ());
143 auto loop_segment_virtual_end =
144 units::ticks (loop_range->loopEndPosition ()->ticks ());
145 auto loop_segment_absolute_start = units::ticks (0.0);
146 auto loop_segment_absolute_end =
147 loop_segment_virtual_end - loop_segment_virtual_start;
148 if (loop_segment_absolute_end > region_length)
149 {
150 const auto delta = loop_segment_absolute_end - region_length;
151 loop_segment_virtual_end -= delta;
152 loop_segment_absolute_end -= delta;
153 }
154
155 while (loop_segment_absolute_start < region_length)
156 {
157 if constexpr (std::is_same_v<RegionT, MidiRegion>)
158 {
159 handle_midi_region_range (
160 region, events,
161 std::make_pair (
162 loop_segment_virtual_start, loop_segment_virtual_end),
163 loop_segment_absolute_start);
164 }
165 else if constexpr (std::is_same_v<RegionT, ChordRegion>)
166 {
167 handle_chord_region_range (
168 region, events,
169 std::make_pair (
170 loop_segment_virtual_start, loop_segment_virtual_end),
171 loop_segment_absolute_start);
172 }
173 else if constexpr (std::is_same_v<RegionT, AudioRegion>)
174 {
175 handle_audio_region_range (
176 region, events,
177 std::make_pair (
178 loop_segment_virtual_start, loop_segment_virtual_end),
179 loop_segment_absolute_start);
180 }
181 else if constexpr (std::is_same_v<RegionT, AutomationRegion>)
182 {
183 handle_automation_region_range (
184 region, events,
185 std::make_pair (
186 loop_segment_virtual_start, loop_segment_virtual_end),
187 loop_segment_absolute_start);
188 }
189
190 // Advance to next segment
191 const auto currentLen =
192 loop_segment_absolute_end - loop_segment_absolute_start;
193 loop_segment_virtual_start =
194 units::ticks (loop_range->loopStartPosition ()->ticks ());
195 loop_segment_virtual_end =
196 units::ticks (loop_range->loopEndPosition ()->ticks ());
197 loop_segment_absolute_start += currentLen;
198 loop_segment_absolute_end += loop_length;
199
200 // Clip final segment to region bounds
201 if (loop_segment_absolute_end > region_length)
202 {
203 const auto delta = loop_segment_absolute_end - region_length;
204 loop_segment_virtual_end -= delta;
205 loop_segment_absolute_end -= delta;
206 }
207 }
208 }
209
210 static void handle_midi_region_range (
211 const MidiRegion &region,
212 juce::MidiMessageSequence &events,
213 std::pair<units::precise_tick_t, units::precise_tick_t> virtual_range,
214 units::precise_tick_t absolute_start);
215
216 static void handle_chord_region_range (
217 const ChordRegion &region,
218 juce::MidiMessageSequence &events,
219 std::pair<units::precise_tick_t, units::precise_tick_t> virtual_range,
220 units::precise_tick_t absolute_start);
221
222 static void handle_audio_region_range (
223 const AudioRegion &region,
224 juce::AudioSampleBuffer &buffer,
225 std::pair<units::precise_tick_t, units::precise_tick_t> virtual_range,
226 units::precise_tick_t absolute_start);
227
228 static void handle_automation_region_range (
229 const AutomationRegion &region,
230 std::vector<float> &values,
231 std::pair<units::precise_tick_t, units::precise_tick_t> virtual_range,
232 units::precise_tick_t absolute_start);
233
237 static void
238 apply_gain_pass (const AudioRegion &region, juce::AudioSampleBuffer &buffer);
239
243 static void apply_region_fades_pass (
244 const AudioRegion &region,
245 juce::AudioSampleBuffer &buffer);
246
250 static void apply_builtin_fades_pass (
251 const AudioRegion &region,
252 juce::AudioSampleBuffer &buffer,
253 int builtin_fade_frames);
254};
255
256} // namespace zrythm::structure::arrangement
Base class for all objects in the arranger.
A region for playing back audio samples.
Represents an automation region, which contains a collection of automation points.
A Region containing MIDI events.
Definition midi_region.h:20
A class that converts region data to serialized formats.
static void serialize_to_sequence(const ChordRegion &region, juce::MidiMessageSequence &events, std::optional< std::pair< double, double > > timeline_range_ticks=std::nullopt)
Serializes a Chord region to a MIDI message sequence.
static void serialize_to_sequence(const MidiRegion &region, juce::MidiMessageSequence &events, std::optional< std::pair< double, double > > timeline_range_ticks=std::nullopt)
Serializes a MIDI region to a MIDI message sequence.
static void serialize_to_automation_values(const AutomationRegion &region, std::vector< float > &values, std::optional< std::pair< double, double > > timeline_range_ticks=std::nullopt)
Serializes an Automation region to sample-accurate automation values.
static void serialize_to_buffer(const AudioRegion &region, juce::AudioSampleBuffer &buffer, std::optional< std::pair< double, double > > timeline_range_ticks=std::nullopt)
Serializes an Audio region to an audio sample buffer.