Zrythm v2.0.0-DEV
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
arranger_object_factory.h
1// SPDX-FileCopyrightText: © 2025 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "gui/backend/backend/settings_manager.h"
7#include "gui/dsp/snap_grid.h"
8#include "structure/arrangement/arranger_object_all.h"
9#include "structure/tracks/track_all.h"
10
11namespace zrythm::structure::arrangement
12{
21class ArrangerObjectFactory : public QObject
22{
23 Q_OBJECT
24 QML_ELEMENT
25
26 using ArrangerObjectRegistry = structure::arrangement::ArrangerObjectRegistry;
27 using TrackResolver = structure::tracks::TrackResolver;
28 using ArrangerObjectSelectionManager =
29 structure::arrangement::ArrangerObjectSelectionManager;
30 using MidiNote = structure::arrangement::MidiNote;
31 using ChordObject = structure::arrangement::ChordObject;
32 using ScaleObject = structure::arrangement::ScaleObject;
33 using AudioRegion = structure::arrangement::AudioRegion;
34 using MidiRegion = structure::arrangement::MidiRegion;
35 using AutomationRegion = structure::arrangement::AutomationRegion;
36 using AutomationPoint = structure::arrangement::AutomationPoint;
37 using ChordRegion = structure::arrangement::ChordRegion;
38 using Marker = structure::arrangement::Marker;
39 using ArrangerObject = structure::arrangement ::ArrangerObject;
40 using MidiLane = structure::tracks::MidiLane;
41 using AudioLane = structure::tracks::AudioLane;
42
43public:
44 ArrangerObjectFactory () = delete;
45 ArrangerObjectFactory (
46 ArrangerObjectRegistry &registry,
47 TrackResolver track_resolver,
48 gui::SettingsManager &settings_mgr,
49 std::function<dsp::FramesPerTick ()> frames_per_tick_getter,
50 gui::SnapGrid &snap_grid_timeline,
51 gui::SnapGrid &snap_grid_editor,
52 AudioClipResolverFunc clip_resolver,
53 RegisterNewAudioClipFunc clip_registration_func,
54 std::function<sample_rate_t ()> sample_rate_provider,
55 std::function<bpm_t ()> bpm_provider,
56 ArrangerObjectSelectionManager timeline_selections_manager,
57 ArrangerObjectSelectionManager midi_selections_manager,
58 ArrangerObjectSelectionManager chord_selections_manager,
59 ArrangerObjectSelectionManager automation_selections_manager,
60 QObject * parent = nullptr)
61 : QObject (parent), object_registry_ (registry),
62 track_resolver_ (std::move (track_resolver)),
63 settings_manager_ (settings_mgr),
64 frames_per_tick_getter_ (std::move (frames_per_tick_getter)),
65 snap_grid_timeline_ (snap_grid_timeline),
66 snap_grid_editor_ (snap_grid_editor),
67 clip_resolver_func_ (std::move (clip_resolver)),
68 new_clip_registration_func_ (std::move (clip_registration_func)),
69 sample_rate_provider_ (std::move (sample_rate_provider)),
70 bpm_provider_ (std::move (bpm_provider)),
71 timeline_selections_manager_ (timeline_selections_manager),
72 midi_selections_manager_ (midi_selections_manager),
73 chord_selections_manager_ (chord_selections_manager),
74 automation_selections_manager_ (automation_selections_manager)
75 {
76 }
77
78 static ArrangerObjectFactory * get_instance ();
79
80 template <structure::arrangement::FinalArrangerObjectSubclass ObjT>
81 class Builder
82 {
83 friend class ArrangerObjectFactory;
84
85 private:
86 explicit Builder (
87 ArrangerObjectRegistry &registry,
88 TrackResolver track_resolver)
89 : registry_ (registry), track_resolver_ (std::move (track_resolver))
90 {
91 }
92
93 Builder &with_settings_manager (gui::SettingsManager &settings_manager)
94 {
95 settings_manager_ = settings_manager;
96 return *this;
97 }
98
99 Builder &with_frames_per_tick (dsp::FramesPerTick framesPerTick)
100 {
101 frames_per_tick_ = framesPerTick;
102 return *this;
103 }
104
105 Builder &with_clip_resolver (const AudioClipResolverFunc &clip_resolver)
106 {
107 clip_resolver_ = clip_resolver;
108 return *this;
109 }
110
111 Builder &with_clip (const AudioClip::Uuid clip_id)
112 requires (std::is_same_v<ObjT, AudioRegion>)
113 {
114 clip_id_.emplace (clip_id);
115 return *this;
116 }
117
118 public:
119 Builder &with_start_ticks (double start_ticks)
120 {
121 assert (settings_manager_.has_value ());
122 assert (frames_per_tick_.has_value ());
123 start_ticks_ = start_ticks;
124
125 return *this;
126 }
127
128 Builder &with_end_ticks (double end_ticks)
129 requires (std::derived_from<ObjT, structure::arrangement::BoundedObject>)
130 {
131 assert (frames_per_tick_.has_value ());
132 end_ticks_ = end_ticks;
133 return *this;
134 }
135
136 Builder &with_name (
137 const QString &name,
138 structure::arrangement::NamedObject::NameValidator validator =
139 [] (const utils::Utf8String &) { return true; })
140 requires (std::derived_from<ObjT, structure::arrangement::NamedObject>)
141 {
142 name_ = name;
143 name_validator_ = validator;
144 return *this;
145 }
146
147 Builder &with_pitch (const int pitch)
148 requires (std::is_same_v<ObjT, MidiNote>)
149 {
150 pitch_ = pitch;
151 return *this;
152 }
153
154 Builder &with_velocity (const int vel)
155 requires (std::is_same_v<ObjT, MidiNote>)
156 {
157 velocity_ = vel;
158 return *this;
159 }
160
161 Builder &with_automatable_value (const double automatable_val)
162 requires (std::is_same_v<ObjT, AutomationPoint>)
163 {
164 automatable_value_ = automatable_val;
165 return *this;
166 }
167
168 Builder &with_chord_descriptor (const int chord_descriptor_index)
169 requires (std::is_same_v<ObjT, ChordObject>)
170 {
171 chord_descriptor_index_ = chord_descriptor_index;
172 return *this;
173 }
174
175 Builder &with_scale (const dsp::MusicalScale scale)
176 requires (std::is_same_v<ObjT, ScaleObject>)
177 {
178 scale_ = scale;
179 return *this;
180 }
181
185 std::unique_ptr<ObjT> build_empty () const
186 {
187 std::unique_ptr<ObjT> ret;
188 if constexpr (std::is_same_v<ObjT, AudioRegion>)
189 {
190 ret = std::make_unique<ObjT> (
191 registry_, track_resolver_, *clip_resolver_);
192 }
193 else if constexpr (std::is_same_v<ObjT, Marker>)
194 {
195 ret = std::make_unique<ObjT> (
196 registry_, track_resolver_, *name_validator_);
197 }
198 else
199 {
200 ret = std::make_unique<ObjT> (registry_, track_resolver_);
201 }
202 return ret;
203 }
204
205 auto build_in_registry ()
206 {
207 auto obj_ref = [&] () {
208 auto obj_unique_ptr = build_empty ();
209 registry_.register_object (obj_unique_ptr.get ());
210 structure::arrangement::ArrangerObjectUuidReference ret_ref{
211 obj_unique_ptr->get_uuid (), registry_
212 };
213 obj_unique_ptr.release ();
214 return ret_ref;
215 }();
216
217 auto * obj = std::get<ObjT *> (obj_ref.get_object ());
218 if (clip_id_)
219 {
220 if constexpr (std::is_same_v<ObjT, AudioRegion>)
221 {
222 obj->set_clip_id (*clip_id_);
223 obj->set_end_pos_full_size (
225 obj->get_position ().frames_
226 + clip_resolver_.value () (*clip_id_)->get_num_frames (),
227 to_ticks_per_frame (*frames_per_tick_) },
228 *frames_per_tick_);
229 }
230 }
231
232 if (end_ticks_)
233 {
234 if constexpr (
235 std::derived_from<ObjT, structure::arrangement::BoundedObject>)
236 {
237 obj->set_end_pos_full_size (
238 dsp::Position (*end_ticks_, *frames_per_tick_),
239 *frames_per_tick_);
240 }
241 }
242
243 // set start ticks after end ticks to avoid position validation failing
244 // due to pos <= end_pos
245 if (start_ticks_)
246 {
247 if (!end_ticks_ && !clip_id_)
248 {
249 if constexpr (
250 std::derived_from<ObjT, structure::arrangement::BoundedObject>)
251 {
252 double len_ticks{};
253 if constexpr (
254 std::derived_from<
255 ObjT, structure::arrangement::TimelineObject>)
256 {
257 len_ticks =
258 settings_manager_
259 ->get_timelineLastCreatedObjectLengthInTicks ();
260 }
261 else
262 {
263 len_ticks =
264 settings_manager_
265 ->get_editorLastCreatedObjectLengthInTicks ();
266 }
267 obj->set_end_pos_full_size (
268 dsp::Position (*start_ticks_ + len_ticks, *frames_per_tick_),
269 *frames_per_tick_);
270 }
271 }
272 obj->position_setter_validated (
273 dsp::Position (*start_ticks_, *frames_per_tick_),
274 to_ticks_per_frame (*frames_per_tick_));
275 }
276
277 if (name_)
278 {
279 if constexpr (
280 std::derived_from<ObjT, structure::arrangement::NamedObject>)
281 {
282 obj->set_name (utils::Utf8String::from_qstring (*name_));
283 }
284 }
285
286 if (pitch_)
287 {
288 if constexpr (std::is_same_v<ObjT, MidiNote>)
289 {
290 obj->setPitch (*pitch_);
291 }
292 }
293
294 if (velocity_)
295 {
296 if constexpr (std::is_same_v<ObjT, MidiNote>)
297 {
298 obj->set_velocity (*velocity_);
299 }
300 }
301
302 if (automatable_value_)
303 {
304 if constexpr (std::is_same_v<ObjT, AutomationPoint>)
305 {
306 obj->setValue (*automatable_value_);
307 }
308 }
309
310 if (scale_)
311 {
312 if constexpr (std::is_same_v<ObjT, ScaleObject>)
313 {
314 obj->set_scale (*scale_);
315 }
316 }
317
318 if constexpr (std::is_same_v<ObjT, AutomationPoint>)
319 {
320 // TODO: add getter/setters on AutomationPoint
321 obj->curve_opts_.algo_ = static_cast<dsp::CurveOptions::Algorithm> (
322 gui::SettingsManager::automationCurveAlgorithm ());
323 }
324
325 if (chord_descriptor_index_)
326 {
327 if constexpr (std::is_same_v<ObjT, ChordObject>)
328 {
329 obj->set_chord_descriptor (*chord_descriptor_index_);
330 }
331 }
332
333 return obj_ref;
334 }
335
336 private:
337 ArrangerObjectRegistry &registry_;
338 TrackResolver track_resolver_;
339 OptionalRef<gui::SettingsManager> settings_manager_;
340 std::optional<dsp::FramesPerTick> frames_per_tick_;
341 std::optional<AudioClipResolverFunc> clip_resolver_;
342 std::optional<AudioClip::Uuid> clip_id_;
343 std::optional<double> start_ticks_;
344 std::optional<double> end_ticks_;
345 std::optional<QString> name_;
346 std::optional<structure::arrangement::NamedObject::NameValidator>
347 name_validator_;
348 std::optional<int> pitch_;
349 std::optional<double> automatable_value_;
350 std::optional<int> chord_descriptor_index_;
351 std::optional<dsp::MusicalScale> scale_;
352 std::optional<int> velocity_;
353 };
354
355 template <typename ObjT> auto get_builder () const
356 {
357 auto builder =
358 Builder<ObjT> (object_registry_, track_resolver_)
359 .with_frames_per_tick (frames_per_tick_getter_ ())
360 .with_clip_resolver (clip_resolver_func_)
361 .with_settings_manager (settings_manager_);
362 return builder;
363 }
364
365private:
369 template <structure::tracks::TrackLaneSubclass TrackLaneT>
370 void add_laned_object (TrackLaneT &lane, auto obj_ref)
371 {
372 using RegionT = typename TrackLaneT::RegionT;
373 std::visit (
374 [&] (auto &&track) {
375 if constexpr (
376 std::is_same_v<
377 typename base_type<decltype (track)>::TrackLaneType, TrackLaneT>)
378 {
379 track->template add_region<RegionT> (
380 obj_ref, nullptr, lane.get_index_in_track (), true);
381 }
382 },
383 convert_to_variant<structure::tracks::LanedTrackPtrVariant> (
384 lane.get_track ()));
385 auto * obj = std::get<RegionT *> (obj_ref.get_object ());
386 timeline_selections_manager_.append_to_selection (obj->get_uuid ());
387 set_selection_handler_to_object (*obj);
388 }
389
393 auto create_audio_region_with_clip (
394 AudioLane &lane,
395 const AudioClip::Uuid &clip_id,
396 double startTicks) const
397 {
398 auto obj =
399 get_builder<AudioRegion> ()
400 .with_start_ticks (startTicks)
401 .with_clip (clip_id)
402 .build_in_registry ();
403 return obj;
404 }
405
412 auto create_audio_region_from_audio_buffer (
413 AudioLane &lane,
414 const utils::audio::AudioBuffer &buf,
415 utils::audio::BitDepth bit_depth,
416 const utils::Utf8String &clip_name,
417 double start_ticks) const
418 {
419 auto clip = std::make_shared<AudioClip> (
420 buf, bit_depth, sample_rate_provider_ (), bpm_provider_ (), clip_name);
421 new_clip_registration_func_ (clip);
422 auto region =
423 create_audio_region_with_clip (lane, clip->get_uuid (), start_ticks);
424 return region;
425 }
426
435 template <structure::arrangement::RegionWithChildren RegionT>
436 auto add_editor_object (
437 RegionT &region,
438 double startTicks,
439 std::variant<int, double> value) -> RegionT::ChildT *
440 {
441 using ChildT = typename RegionT::ChildT;
442 auto builder = get_builder<ChildT> ().with_start_ticks (startTicks);
443 if constexpr (std::is_same_v<ChildT, MidiNote>)
444 {
445 const auto ival = std::get<int> (value);
446 assert (ival >= 0 && ival < 128);
447 builder.with_pitch (ival);
448 }
449 else if constexpr (std::is_same_v<ChildT, AutomationPoint>)
450 {
451 builder.with_automatable_value (std::get<double> (value));
452 }
453 else if constexpr (std::is_same_v<ChildT, ChordObject>)
454 {
455 builder.with_chord_descriptor (std::get<int> (value));
456 }
457 auto obj_ref = builder.build_in_registry ();
458 region.add_object (obj_ref);
459 auto obj = std::get<ChildT *> (obj_ref.get_object ());
460 {
461 auto sel_mgr = get_selection_manager_for_object (*obj);
462 sel_mgr.append_to_selection (obj->get_uuid ());
463 set_selection_handler_to_object (*obj);
464 }
465 return obj;
466 }
467
468public:
479 const AudioClip::Uuid &clip_id,
480 double start_ticks)
481 {
482 // clip must already be registered before calling this method
483 assert (clip_resolver_func_ (clip_id) != nullptr);
484 auto obj_ref = create_audio_region_with_clip (lane, clip_id, start_ticks);
485 add_laned_object (lane, obj_ref);
486 return std::get<AudioRegion *> (obj_ref.get_object ());
487 }
488
489 ScaleObject * add_scale_object (
491 const dsp::MusicalScale &scale,
492 double start_ticks)
493 {
494 auto obj_ref =
495 get_builder<ScaleObject> ()
496 .with_start_ticks (start_ticks)
497 .with_scale (scale)
498 .build_in_registry ();
499 chord_track.ArrangerObjectOwner<ScaleObject>::add_object (obj_ref);
500 return std::get<ScaleObject *> (obj_ref.get_object ());
501 }
502
503 Q_INVOKABLE Marker * addMarker (
504 structure::tracks::MarkerTrack * markerTrack,
505 const QString &name,
506 double startTicks)
507
508 {
509 auto marker_ref =
510 get_builder<Marker> ()
511 .with_start_ticks (startTicks)
512 .with_name (
513 name,
514 [markerTrack] (const utils::Utf8String &inner_name) {
515 return markerTrack->validate_marker_name (inner_name);
516 })
517 .build_in_registry ();
518 markerTrack->add_object (marker_ref);
519 return std::get<Marker *> (marker_ref.get_object ());
520 }
521
522 Q_INVOKABLE MidiRegion *
523 addEmptyMidiRegion (structure::tracks::MidiLane * lane, double startTicks)
524 {
525 auto mr_ref =
526 get_builder<MidiRegion> ()
527 .with_start_ticks (startTicks)
528 .build_in_registry ();
529 add_laned_object (*lane, mr_ref);
530 return std::get<MidiRegion *> (mr_ref.get_object ());
531 }
532
533 Q_INVOKABLE ChordRegion *
534 addEmptyChordRegion (structure::tracks::ChordTrack * track, double startTicks)
535 {
536 auto cr_ref =
537 get_builder<ChordRegion> ()
538 .with_start_ticks (startTicks)
539 .build_in_registry ();
540 track->Track::add_region<ChordRegion> (cr_ref, nullptr, std::nullopt, true);
541 return std::get<ChordRegion *> (cr_ref.get_object ());
542 }
543
544 Q_INVOKABLE AutomationRegion * addEmptyAutomationRegion (
545 tracks::AutomationTrack * automationTrack,
546 double startTicks)
547
548 {
549 auto ar_ref =
550 get_builder<AutomationRegion> ()
551 .with_start_ticks (startTicks)
552 .build_in_registry ();
553 auto track_var = automationTrack->get_track ();
554 std::visit (
555 [&] (auto &&track) {
556 track->structure::tracks::Track::template add_region<AutomationRegion> (
557 ar_ref, automationTrack, std::nullopt, true);
558 },
559 track_var);
560 return std::get<AutomationRegion *> (ar_ref.get_object ());
561 }
562
563 AudioRegion * add_empty_audio_region_for_recording (
564 AudioLane &lane,
565 int num_channels,
566 const utils::Utf8String &clip_name,
567 double start_ticks)
568 {
569 auto clip = std::make_shared<AudioClip> (
570 num_channels, 1, sample_rate_provider_ (), bpm_provider_ (), clip_name);
571 new_clip_registration_func_ (clip);
572 auto region_ref =
573 create_audio_region_with_clip (lane, clip->get_uuid (), start_ticks);
574 add_laned_object (lane, region_ref);
575 return std::get<AudioRegion *> (region_ref.get_object ());
576 }
577
578 Q_INVOKABLE AudioRegion * addAudioRegionFromFile (
579 AudioLane * lane,
580 const QString &absPath,
581 double startTicks)
582 {
583 auto clip = std::make_shared<AudioClip> (
584 utils::Utf8String::from_qstring (absPath), sample_rate_provider_ (),
585 bpm_provider_ ());
586 new_clip_registration_func_ (clip);
587 auto ar_ref =
588 create_audio_region_with_clip (*lane, clip->get_uuid (), startTicks);
589 add_laned_object (*lane, ar_ref);
590 return std::get<AudioRegion *> (ar_ref.get_object ());
591 }
592
597 Q_INVOKABLE MidiRegion * addMidiRegionFromChordDescriptor (
598 MidiLane * lane,
599 const dsp::ChordDescriptor &descr,
600 double startTicks);
601
610 Q_INVOKABLE MidiRegion * addMidiRegionFromMidiFile (
611 MidiLane * lane,
612 const QString &absolutePath,
613 double startTicks,
614 int midiTrackIndex);
615
616 Q_INVOKABLE MidiNote *
617 addMidiNote (MidiRegion * region, double startTicks, int pitch)
618 {
619 return add_editor_object (*region, startTicks, pitch);
620 }
621
622 Q_INVOKABLE AutomationPoint *
623 addAutomationPoint (AutomationRegion * region, double startTicks, double value)
624
625 {
626 return add_editor_object (*region, startTicks, value);
627 }
628
629 Q_INVOKABLE ChordObject *
630 addChordObject (ChordRegion * region, double startTicks, const int chordIndex)
631
632 {
633 return add_editor_object (*region, startTicks, chordIndex);
634 }
635
643 AudioLane &lane,
644 const utils::audio::AudioBuffer &buf,
645 utils::audio::BitDepth bit_depth,
646 const utils::Utf8String &clip_name,
647 double start_ticks) const
648 {
649 return create_audio_region_from_audio_buffer (
650 lane, buf, bit_depth, clip_name, start_ticks);
651 }
652
653 template <structure::arrangement::FinalArrangerObjectSubclass ObjT>
654 auto clone_new_object_identity (const ObjT &other) const
655 {
656 if constexpr (std::is_same_v<ObjT, AudioRegion>)
657 {
658 return object_registry_.clone_object (
659 other, object_registry_, track_resolver_, clip_resolver_func_);
660 }
661 else
662 {
663 return object_registry_.clone_object (
664 other, object_registry_, track_resolver_);
665 }
666 }
667
668 template <structure::arrangement::FinalArrangerObjectSubclass ObjT>
669 auto clone_object_snapshot (const ObjT &other, QObject &owner) const
670 {
671 ObjT * new_obj{};
672 if constexpr (std::is_same_v<ObjT, AudioRegion>)
673 {
674 // TODO
675 new_obj = utils::clone_qobject (
676 other, &owner, utils::ObjectCloneType::Snapshot, object_registry_,
677 track_resolver_, clip_resolver_func_);
678 }
679 else if constexpr (std::is_same_v<ObjT, Marker>)
680 {
681 new_obj = utils::clone_qobject (
682 other, &owner, utils::ObjectCloneType::Snapshot, object_registry_,
683 track_resolver_, [] (const auto &name) { return true; });
684 }
685 else
686 {
687 new_obj = utils::clone_qobject (
688 other, &owner, utils::ObjectCloneType::Snapshot, object_registry_,
689 track_resolver_);
690 }
691 return new_obj;
692 }
693
694 template <structure::arrangement::FinalArrangerObjectSubclass ObjT>
695 auto get_selection_manager_for_object (const ObjT &obj) const
696 {
697 if constexpr (
698 std::derived_from<ObjT, structure::arrangement::TimelineObject>)
699 {
700 return timeline_selections_manager_;
701 }
702 else if constexpr (std::is_same_v<ObjT, MidiNote>)
703 {
704 return midi_selections_manager_;
705 }
706 else if constexpr (std::is_same_v<ObjT, AutomationPoint>)
707 {
708 return automation_selections_manager_;
709 }
710 else if constexpr (std::is_same_v<ObjT, ChordObject>)
711 {
712 return chord_selections_manager_;
713 }
714 else
715 {
716 static_assert (false);
717 }
718 }
719
720 template <structure::arrangement::FinalArrangerObjectSubclass ObjT>
721 void set_selection_handler_to_object (ObjT &obj)
722 {
723 auto sel_mgr = get_selection_manager_for_object (obj);
724 obj.set_selection_status_getter ([sel_mgr] (const ArrangerObject::Uuid &id) {
725 return sel_mgr.is_selected (id);
726 });
727 }
728
729private:
730 ArrangerObjectRegistry &object_registry_;
731 TrackResolver track_resolver_;
732 gui::SettingsManager &settings_manager_;
733 std::function<dsp::FramesPerTick ()> frames_per_tick_getter_;
734 gui::SnapGrid &snap_grid_timeline_;
735 gui::SnapGrid &snap_grid_editor_;
736 AudioClipResolverFunc clip_resolver_func_;
737 RegisterNewAudioClipFunc new_clip_registration_func_;
738 std::function<sample_rate_t ()> sample_rate_provider_;
739 std::function<bpm_t ()> bpm_provider_;
740 ArrangerObjectSelectionManager timeline_selections_manager_;
741 ArrangerObjectSelectionManager midi_selections_manager_;
742 ArrangerObjectSelectionManager chord_selections_manager_;
743 ArrangerObjectSelectionManager automation_selections_manager_;
744};
745}
A ChordDescriptor describes a chord and is not linked to any specific object by itself.
Algorithm
The algorithm to use for curves.
Definition curve.h:31
Musical scale descriptor.
Represents the position of an object.
Definition position.h:65
Snap/grid information.
Definition snap_grid.h:45
std::unique_ptr< ObjT > build_empty() const
Returns an instantiated object to be used for deserialization.
AudioRegion * add_audio_region_with_clip(structure::tracks::AudioLane &lane, const AudioClip::Uuid &clip_id, double start_ticks)
Q_INVOKABLE MidiRegion * addMidiRegionFromChordDescriptor(MidiLane *lane, const dsp::ChordDescriptor &descr, double startTicks)
Creates a MIDI region at lane from the given descr starting at startTicks.
Q_INVOKABLE MidiRegion * addMidiRegionFromMidiFile(MidiLane *lane, const QString &absolutePath, double startTicks, int midiTrackIndex)
Creates a MIDI region at lane from MIDI file path abs_path starting at startTicks.
auto create_audio_region_from_audio_buffer_FIXME(AudioLane &lane, const utils::audio::AudioBuffer &buf, utils::audio::BitDepth bit_depth, const utils::Utf8String &clip_name, double start_ticks) const
Temporary solution for splitting regions.
An AudioRegion represents a region of audio within a Track.
An automation point inside an AutomationTrack.
Represents an automation region, which contains a collection of automation points.
The ChordObject class represents a chord inside a ChordRegion.
Marker for the MarkerTrack.
Definition marker.h:18
A MIDI note inside a Region shown in the piano roll.
Definition midi_note.h:26
A Region containing MIDI events.
Definition midi_region.h:33
The ChordTrack class is responsible for managing the chord and scale information in the project.
Definition chord_track.h:39
void register_object(VariantT obj_ptr)
Registers an object.
Lightweight UTF-8 string wrapper with safe conversions.
Definition string.h:39
uint32_t sample_rate_t
Sample rate.
Definition types.h:61
float bpm_t
The BPM type.
Definition types.h:73
@ Snapshot
Creates a snapshot of the object with the same identity.
Definition icloneable.h:24