Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
audio_clip_waveform_canvas_item.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <cstdint>
7#include <vector>
8
9#include "gui/qquick/waveform_canvas_item.h"
10#include "gui/qquick/waveform_canvas_renderer.h"
11#include "structure/arrangement/audio_clip.h"
12
13#include <QPointer>
14#include <QtQmlIntegration/qqmlintegration.h>
15
16namespace zrythm::structure::arrangement
17{
18class AudioClip;
19}
20
21namespace zrythm::gui::qquick
22{
23
33class AudioClipWaveformCanvasItem : public WaveformCanvasItem
34{
35 Q_OBJECT
36 QML_NAMED_ELEMENT (AudioClipWaveformCanvas)
37
38 Q_PROPERTY (
39 zrythm::structure::arrangement::AudioClip * audioClip READ audioClip WRITE
40 setAudioClip NOTIFY audioClipChanged)
41 Q_PROPERTY (
42 QObject * tempoMap READ tempoMap WRITE setTempoMap NOTIFY tempoMapChanged)
43
44public:
45 explicit AudioClipWaveformCanvasItem (QQuickItem * parent = nullptr);
46
47 structure::arrangement::AudioClip * audioClip () const { return audio_clip_; }
48 void setAudioClip (structure::arrangement::AudioClip * clip);
49
50 QObject * tempoMap () const { return tempo_map_; }
51 void setTempoMap (QObject * tempoMap);
55 bool hasLoop () const
56 {
57 return audio_clip_ != nullptr && audio_clip_->looped ()
58 && last_snapshot_.loop_end_samples > last_snapshot_.loop_start_samples;
59 }
63 int64_t loopStartFrame () const { return last_snapshot_.loop_start_samples; }
64 int64_t loopEndFrame () const { return last_snapshot_.loop_end_samples; }
65 int64_t clipStartFrame () const { return last_snapshot_.clip_start_samples; }
66
67 /// Where the loop region begins in the serialized buffer. The buffer layout
68 /// is: [intro: clip_start→loop_end] [loop: loop_start→loop_end] repeated.
69 /// So the loop region starts at frame (loop_end - clip_start).
70 int64_t loopRegionBufferStart () const
71 {
72 return last_snapshot_.loop_end_samples - last_snapshot_.clip_start_samples;
73 }
74
79 std::vector<int64_t> computeTimelineFrameMapping (
80 int canvas_width,
81 qreal reference_width,
82 qreal reference_x) const;
83
84Q_SIGNALS:
85 void audioClipChanged ();
86 void tempoMapChanged ();
87
88private:
95 struct ClipSnapshot
96 {
97 int64_t clip_start_samples{};
98 int64_t loop_start_samples{};
99 int64_t loop_end_samples{};
100 int64_t length_samples{};
101 int64_t fade_in_samples{};
102 int64_t fade_out_samples{};
103 float gain{ 1.0f };
104
105 friend bool
106 operator== (const ClipSnapshot &, const ClipSnapshot &) = default;
107 };
108
109 ClipSnapshot take_snapshot () const;
110
111private Q_SLOTS:
112 void handle_property_change ();
113
114private:
115 QPointer<structure::arrangement::AudioClip> audio_clip_;
116 std::vector<QMetaObject::Connection> clip_connections_;
117 QPointer<QObject> tempo_map_;
118 std::vector<QMetaObject::Connection> tempo_map_connections_;
119 ClipSnapshot last_snapshot_;
120};
121
122} // namespace zrythm::gui::qquick
std::vector< int64_t > computeTimelineFrameMapping(int canvas_width, qreal reference_width, qreal reference_x) const
Computes a per-pixel frame mapping that accounts for the tempo map's non-linear tick-to-sample conver...
int64_t loopStartFrame() const
Sample-space offset of the loop-start position relative to clip start (content-space,...
bool hasLoop() const
Only wrap when the clip is actually looped.
int64_t loopRegionBufferStart() const
Where the loop region begins in the serialized buffer.
A clip for playing back audio samples.
Definition audio_clip.h:24