1 /*
2 * Copyright (C) 2018-2021 Alexandros Theodotou <alex at zrythm dot org>
3 *
4 * This file is part of Zrythm
5 *
6 * Zrythm is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Affero General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Zrythm is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Affero General Public License for more details.
15 *
16 * You should have received a copy of the GNU Affero General Public License
17 * along with Zrythm. If not, see <https://www.gnu.org/licenses/>.
18 */
19
20 /**
21 * \file
22 *
23 * A region in the timeline.
24 */
25 #ifndef __AUDIO_REGION_H__
26 #define __AUDIO_REGION_H__
27
28 #include "audio/automation_point.h"
29 #include "audio/chord_object.h"
30 #include "audio/midi_note.h"
31 #include "audio/midi_region.h"
32 #include "audio/position.h"
33 #include "audio/region_identifier.h"
34 #include "gui/backend/arranger_object.h"
35 #include "utils/yaml.h"
36
37 #include <gtk/gtk.h>
38
39 typedef struct _RegionWidget RegionWidget;
40 typedef struct Channel Channel;
41 typedef struct Track Track;
42 typedef struct MidiNote MidiNote;
43 typedef struct TrackLane TrackLane;
44 typedef struct _AudioClipWidget AudioClipWidget;
45 typedef struct RegionLinkGroup RegionLinkGroup;
46 typedef struct Stretcher Stretcher;
47 typedef struct AudioClip AudioClip;
48
49 /**
50 * @addtogroup audio
51 *
52 * @{
53 */
54
55 #define REGION_SCHEMA_VERSION 1
56
57 #define REGION_MAGIC 93075327
58 #define IS_REGION(x) \
59 (((ZRegion *) x)->magic == REGION_MAGIC)
60 #define IS_REGION_AND_NONNULL(x) \
61 (x && IS_REGION (x))
62
63 #define REGION_PRINTF_FILENAME "%s_%s.mid"
64
65 #define region_is_selected(r) \
66 arranger_object_is_selected ( \
67 (ArrangerObject *) r)
68
69 /**
70 * Musical mode setting for audio regions.
71 */
72 typedef enum RegionMusicalMode
73 {
74 /** Inherit from global musical mode setting. */
75 REGION_MUSICAL_MODE_INHERIT,
76 /** Musical mode off - don't auto-stretch when
77 * BPM changes. */
78 REGION_MUSICAL_MODE_OFF,
79 /** Musical mode on - auto-stretch when BPM
80 * changes. */
81 REGION_MUSICAL_MODE_ON,
82 } RegionMusicalMode;
83
84 static const cyaml_strval_t
85 region_musical_mode_strings[] =
86 {
87 { __("Inherit"),
88 REGION_MUSICAL_MODE_INHERIT },
89 { __("Off"),
90 REGION_MUSICAL_MODE_OFF },
91 { __("On"),
92 REGION_MUSICAL_MODE_ON },
93 };
94
95 /**
96 * A region (clip) is an object on the timeline that
97 * contains either MidiNote's or AudioClip's.
98 *
99 * It is uniquely identified using its name, so it
100 * must be unique throughout the Project.
101 */
102 typedef struct ZRegion
103 {
104 /** Base struct. */
105 ArrangerObject base;
106
107 int schema_version;
108
109 /** Unique ID. */
110 RegionIdentifier id;
111
112 /** Name to be shown on the widget. */
113 char * name;
114
115 /** Escaped name for drawing. */
116 char * escaped_name;
117
118 /**
119 * TODO region color independent of track.
120 *
121 * If null, the track color is used.
122 */
123 GdkRGBA color;
124
125 /* ==== MIDI REGION ==== */
126
127 /** MIDI notes. */
128 MidiNote ** midi_notes;
129 int num_midi_notes;
130 size_t midi_notes_size;
131
132 /**
133 * Unended notes started in recording with
134 * MIDI NOTE ON
135 * signal but haven't received a NOTE OFF yet.
136 *
137 * This is also used temporarily when reading
138 * from MIDI files.
139 *
140 * FIXME allocate.
141 *
142 * @note These are present in
143 * \ref ZRegion.midi_notes and must not be
144 * free'd separately.
145 */
146 MidiNote * unended_notes[12000];
147 int num_unended_notes;
148
149 /* ==== MIDI REGION END ==== */
150
151 /* ==== AUDIO REGION ==== */
152
153 /** Audio pool ID of the associated audio file,
154 * mostly used during serialization. */
155 int pool_id;
156
157 /**
158 * Whether currently running the stretching
159 * algorithm.
160 *
161 * If this is true, region drawing will be
162 * deferred.
163 */
164 bool stretching;
165
166 /**
167 * The length before stretching, in ticks.
168 */
169 double before_length;
170
171 /** Used during arranger UI overlay actions. */
172 double stretch_ratio;
173
174 /**
175 * Whether to read the clip from the pool (used
176 * in most cases).
177 */
178 bool read_from_pool;
179
180 /** Gain to apply to the audio (amplitude
181 * 0.0-2.0). */
182 float gain;
183
184 /**
185 * Clip to read frames from, if not from the pool.
186 */
187 AudioClip * clip;
188
189 #if 0
190 /**
191 * Frames to actually use, interleaved.
192 *
193 * Properties such as \ref AudioClip.channels can
194 * be fetched from the AudioClip.
195 */
196 sample_t * frames;
197 size_t num_frames;
198
199 /**
200 * Per-channel frames for convenience.
201 */
202 sample_t * ch_frames[16];
203 #endif
204
205 /** Musical mode setting. */
206 RegionMusicalMode musical_mode;
207
208 /** Array of split points. */
209 Position * split_points;
210 int num_split_points;
211 size_t split_points_size;
212
213 /* ==== AUDIO REGION END ==== */
214
215 /* ==== AUTOMATION REGION ==== */
216
217 /**
218 * The automation points this region contains.
219 *
220 * Could also be used in audio regions for volume
221 * automation.
222 *
223 * Must always stay sorted by position.
224 */
225 AutomationPoint ** aps;
226 int num_aps;
227 size_t aps_size;
228
229 /** Last recorded automation point. */
230 AutomationPoint * last_recorded_ap;
231
232 /* ==== AUTOMATION REGION END ==== */
233
234 /* ==== CHORD REGION ==== */
235
236 /** ChordObject's in this Region. */
237 ChordObject ** chord_objects;
238 int num_chord_objects;
239 size_t chord_objects_size;
240
241 /* ==== CHORD REGION END ==== */
242
243 /**
244 * Set to ON during bouncing if this
245 * region should be included.
246 *
247 * Only relevant for audio and midi regions.
248 */
249 int bounce;
250
251 /* --- drawing caches --- */
252
253 /* New region drawing needs to be cached in the
254 * following situations:
255 *
256 * 1. when hidden part of the region is revealed
257 * (on x axis).
258 * TODO max 140% of the region should be
259 * cached (20% before and 20% after if before/
260 * after is not fully visible)
261 * 2. when full rect (x/width) changes
262 * 3. when a region marker is moved
263 * 4. when the clip actually changes (use
264 * last-change timestamp on the clip or region)
265 * 5. when fades change
266 * 6. when region height changes (track/lane)
267 */
268
269 /** Cache layout for drawing the name. */
270 PangoLayout * layout;
271
272 /** Cache layout for drawing the chord names
273 * inside the region. */
274 PangoLayout * chords_layout;
275
276 /* these are used for caching */
277 GdkRectangle last_main_full_rect;
278
279 /** Last main draw rect. */
280 GdkRectangle last_main_draw_rect;
281
282 /* these are used for caching */
283 GdkRectangle last_lane_full_rect;
284
285 /** Last lane draw rect. */
286 GdkRectangle last_lane_draw_rect;
287
288 /** Last timestamp the audio clip or its contents
289 * changed. */
290 gint64 last_clip_change;
291
292 /** Last timestamp the region was cached. */
293 gint64 last_cache_time;
294
295 /** Last known marker positions (only positions
296 * are used). */
297 ArrangerObject last_positions_obj;
298
299 /* --- drawing caches end --- */
300
301 int magic;
302 } ZRegion;
303
304 static const cyaml_schema_field_t
305 region_fields_schema[] =
306 {
307 YAML_FIELD_INT (ZRegion, schema_version),
308 YAML_FIELD_MAPPING_EMBEDDED (
309 ZRegion, base, arranger_object_fields_schema),
310 YAML_FIELD_MAPPING_EMBEDDED (
311 ZRegion, id, region_identifier_fields_schema),
312 YAML_FIELD_STRING_PTR (ZRegion, name),
313 YAML_FIELD_INT (ZRegion, pool_id),
314 YAML_FIELD_FLOAT (ZRegion, gain),
315 CYAML_FIELD_SEQUENCE_COUNT (
316 "midi_notes",
317 CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
318 ZRegion, midi_notes, num_midi_notes,
319 &midi_note_schema, 0, CYAML_UNLIMITED),
320 CYAML_FIELD_SEQUENCE_COUNT (
321 "aps", CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
322 ZRegion, aps, num_aps,
323 &automation_point_schema, 0, CYAML_UNLIMITED),
324 CYAML_FIELD_SEQUENCE_COUNT (
325 "chord_objects",
326 CYAML_FLAG_POINTER | CYAML_FLAG_OPTIONAL,
327 ZRegion, chord_objects, num_chord_objects,
328 &chord_object_schema, 0, CYAML_UNLIMITED),
329 YAML_FIELD_ENUM (
330 ZRegion, musical_mode,
331 region_musical_mode_strings),
332
333 CYAML_FIELD_END
334 };
335
336 static const cyaml_schema_value_t
337 region_schema =
338 {
339 YAML_VALUE_PTR_NULLABLE (
340 ZRegion, region_fields_schema),
341 };
342
343 /**
344 * Returns if the given ZRegion type can have fades.
345 */
346 #define region_type_can_fade(rtype) \
347 (rtype == REGION_TYPE_AUDIO)
348
349 /**
350 * Only to be used by implementing structs.
351 */
352 void
353 region_init (
354 ZRegion * region,
355 const Position * start_pos,
356 const Position * end_pos,
357 unsigned int track_name_hash,
358 int lane_pos,
359 int idx_inside_lane);
360
361 /**
362 * Looks for the ZRegion matching the identifier.
363 */
364 HOT
365 NONNULL
366 ZRegion *
367 region_find (
368 const RegionIdentifier * const id);
369
370 #if 0
371 static inline void
372 region_set_track_name_hash (
373 ZRegion * self,
374 unsigned int name_hash)
375 {
376 self->id.track_name_hash = name_hash;
377 }
378 #endif
379
380 NONNULL
381 void
382 region_print_to_str (
383 const ZRegion * self,
384 char * buf,
385 const size_t buf_size);
386
387 /**
388 * Print region info for debugging.
389 */
390 NONNULL
391 void
392 region_print (
393 const ZRegion * region);
394
395 TrackLane *
396 region_get_lane (
397 const ZRegion * region);
398
399 /**
400 * Returns the region's link group.
401 */
402 RegionLinkGroup *
403 region_get_link_group (
404 ZRegion * self);
405
406 /**
407 * Sets the link group to the region.
408 *
409 * @param group_idx If -1, the region will be
410 * removed from its current link group, if any.
411 */
412 void
413 region_set_link_group (
414 ZRegion * region,
415 int group_idx,
416 bool update_identifier);
417
418 NONNULL
419 bool
420 region_has_link_group (
421 ZRegion * region);
422
423 /**
424 * Returns the MidiNote matching the properties of
425 * the given MidiNote.
426 *
427 * Used to find the actual MidiNote in the region
428 * from a cloned MidiNote (e.g. when doing/undoing).
429 */
430 MidiNote *
431 region_find_midi_note (
432 ZRegion * r,
433 MidiNote * _mn);
434
435 /**
436 * Converts frames on the timeline (global)
437 * to local frames (in the clip).
438 *
439 * If normalize is 1 it will only return a position
440 * from 0 to loop_end (it will traverse the
441 * loops to find the appropriate position),
442 * otherwise it may exceed loop_end.
443 *
444 * @param timeline_frames Timeline position in
445 * frames.
446 *
447 * @return The local frames.
448 */
449 NONNULL
450 HOT
451 long
452 region_timeline_frames_to_local (
453 const ZRegion * const self,
454 const long timeline_frames,
455 const bool normalize);
456
457 /**
458 * Returns the number of frames until the next
459 * loop end point or the end of the region.
460 *
461 * @param[in] timeline_frames Global frames at
462 * start.
463 * @param[out] ret_frames Return frames.
464 * @param[out] is_loop Whether the return frames
465 * are for a loop (if false, the return frames
466 * are for the region's end).
467 */
468 NONNULL
469 void
470 region_get_frames_till_next_loop_or_end (
471 const ZRegion * const self,
472 const long timeline_frames,
473 long * ret_frames,
474 bool * is_loop);
475
476 /**
477 * Sets the track lane.
478 */
479 NONNULL
480 void
481 region_set_lane (
482 ZRegion * self,
483 const TrackLane * const lane);
484
485 /**
486 * Generates a name for the ZRegion, either using
487 * the given AutomationTrack or Track, or appending
488 * to the given base name.
489 */
490 void
491 region_gen_name (
492 ZRegion * region,
493 const char * base_name,
494 AutomationTrack * at,
495 Track * track);
496
497 /**
498 * Stretch the region's contents.
499 *
500 * This should be called right after changing the
501 * region's size.
502 *
503 * @param ratio The ratio to stretch by.
504 */
505 NONNULL
506 void
507 region_stretch (
508 ZRegion * self,
509 double ratio);
510
511 /**
512 * To be called every time the identifier changes
513 * to update the region's children.
514 */
515 NONNULL
516 void
517 region_update_identifier (
518 ZRegion * self);
519
520 /**
521 * Updates all other regions in the region link
522 * group, if any.
523 */
524 NONNULL
525 void
526 region_update_link_group (
527 ZRegion * self);
528
529 /**
530 * Moves the given ZRegion to the given TrackLane.
531 *
532 * Works with TrackLane's of other Track's as well.
533 *
534 * Maintains the selection status of the
535 * Region.
536 *
537 * Assumes that the ZRegion is already in a
538 * TrackLane.
539 *
540 * @param index_in_lane Index in lane in the
541 * new track to insert the region to, or -1 to
542 * append.
543 */
544 void
545 region_move_to_lane (
546 ZRegion * region,
547 TrackLane * lane,
548 int index_in_lane);
549
550 /**
551 * Moves the ZRegion to the given Track, maintaining
552 * the selection status of the ZRegion and the
553 * TrackLane position.
554 *
555 * Assumes that the ZRegion is already in a
556 * TrackLane.
557 *
558 * @param index_in_lane Index in lane in the
559 * new track to insert the region to, or -1 to
560 * append.
561 */
562 void
563 region_move_to_track (
564 ZRegion * region,
565 Track * track,
566 int index_in_lane);
567
568 /**
569 * Returns if the given ZRegion type can exist
570 * in TrackLane's.
571 */
572 CONST
573 static inline int
region_type_has_lane(const RegionType type)574 region_type_has_lane (
575 const RegionType type)
576 {
577 return
578 type == REGION_TYPE_MIDI ||
579 type == REGION_TYPE_AUDIO;
580 }
581
582 /**
583 * Sets the automation track.
584 */
585 void
586 region_set_automation_track (
587 ZRegion * region,
588 AutomationTrack * at);
589
590 /**
591 * Gets the AutomationTrack using the saved index.
592 */
593 AutomationTrack *
594 region_get_automation_track (
595 const ZRegion * const region);
596
597 /**
598 * Copies the data from src to dest.
599 *
600 * Used when doing/undoing changes in name,
601 * clip start point, loop start point, etc.
602 */
603 void
604 region_copy (
605 ZRegion * src,
606 ZRegion * dest);
607
608 /**
609 * Returns if the position is inside the region
610 * or not.
611 *
612 * FIXME move to arranger object
613 *
614 * @param gframes Global position in frames.
615 * @param inclusive Whether the last frame should
616 * be counted as part of the region.
617 */
618 int
619 region_is_hit (
620 const ZRegion * region,
621 const long gframes,
622 const int inclusive);
623
624 /**
625 * Returns if any part of the ZRegion is inside the
626 * given range, inclusive.
627 *
628 * FIXME move to arranger object
629 */
630 int
631 region_is_hit_by_range (
632 const ZRegion * region,
633 const long gframes_start,
634 const long gframes_end,
635 const bool end_inclusive);
636
637 /**
638 * Returns the region at the given position in the
639 * given Track.
640 *
641 * @param at The automation track to look in.
642 * @param track The track to look in, if at is
643 * NULL.
644 * @param pos The position.
645 */
646 ZRegion *
647 region_at_position (
648 Track * track,
649 AutomationTrack * at,
650 Position * pos);
651
652 /**
653 * Generates the filename for this region.
654 *
655 * MUST be free'd.
656 */
657 char *
658 region_generate_filename (ZRegion * region);
659
660 void
661 region_get_type_as_string (
662 RegionType type,
663 char * buf);
664
665 /**
666 * Returns if this region is currently being
667 * recorded onto.
668 */
669 bool
670 region_is_recording (
671 ZRegion * self);
672
673 /**
674 * Returns whether the region is effectively in
675 * musical mode.
676 *
677 * @note Only applicable to audio regions.
678 */
679 bool
680 region_get_musical_mode (
681 ZRegion * self);
682
683 /**
684 * Wrapper for adding an arranger object.
685 */
686 void
687 region_add_arranger_object (
688 ZRegion * self,
689 ArrangerObject * obj,
690 bool fire_events);
691
692 void
693 region_create_link_group_if_none (
694 ZRegion * region);
695
696 /**
697 * Removes the link group from the region, if any.
698 */
699 void
700 region_unlink (
701 ZRegion * region);
702
703 /**
704 * Removes all children objects from the region.
705 */
706 void
707 region_remove_all_children (
708 ZRegion * region);
709
710 /**
711 * Clones and copies all children from \ref src to
712 * \ref dest.
713 */
714 void
715 region_copy_children (
716 ZRegion * dest,
717 ZRegion * src);
718
719 NONNULL
720 static inline bool
region_is_looped(const ZRegion * const self)721 region_is_looped (
722 const ZRegion * const self)
723 {
724 ArrangerObject * obj = (ArrangerObject *) self;
725 return
726 obj->loop_start_pos.ticks > 0
727 ||
728 (obj->end_pos.ticks - obj->pos.ticks) >
729 (obj->loop_end_pos.ticks +
730 /* add some buffer because these are not
731 * accurate */
732 0.1);
733 }
734
735 /**
736 * Returns the ArrangerSelections based on the
737 * given region type.
738 */
739 ArrangerSelections *
740 region_get_arranger_selections (
741 ZRegion * self);
742
743 /**
744 * Sanity checking.
745 */
746 bool
747 region_validate (
748 ZRegion * self,
749 bool is_project);
750
751 /**
752 * Disconnects the region and anything using it.
753 *
754 * Does not free the ZRegion or its children's
755 * resources.
756 */
757 void
758 region_disconnect (
759 ZRegion * self);
760
761 /**
762 * @}
763 */
764
765 #endif // __AUDIO_REGION_H__
766