Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
tick_types.h
1// SPDX-FileCopyrightText: © 2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include "utils/units.h"
7
8#include <fmt/format.h>
9
10namespace zrythm::dsp
11{
12
32template <typename Q> struct BasicTimelineTick
33{
34 Q value_{};
35
36 // --- Default special members ---
37 constexpr BasicTimelineTick () = default;
38 constexpr BasicTimelineTick (const BasicTimelineTick &) = default;
39 constexpr BasicTimelineTick (BasicTimelineTick &&) noexcept = default;
40 constexpr BasicTimelineTick &operator= (const BasicTimelineTick &) = default;
41 constexpr BasicTimelineTick &
42 operator= (BasicTimelineTick &&) noexcept = default;
43
45 template <typename Q2>
46 requires std::convertible_to<Q2, Q>
47 constexpr explicit BasicTimelineTick (Q2 q) : value_ (std::move (q))
48 {
49 }
50
51 // --- Cross-precision constructor (delegates to au) ---
52
54 template <typename Q2>
55 requires (!std::same_as<Q, Q2>) && std::convertible_to<const Q2 &, Q>
56 constexpr BasicTimelineTick (const BasicTimelineTick<Q2> &other)
57 : value_ (other.value_)
58 {
59 }
60
61 // --- Comparisons (same type only — prevents cross-domain mixing) ---
62 bool operator== (const BasicTimelineTick &) const = default;
63 auto operator<=> (const BasicTimelineTick &) const = default;
64
65 // --- Arithmetic (same type only) ---
66 BasicTimelineTick operator+ (const BasicTimelineTick &o) const
67 {
68 return BasicTimelineTick{ value_ + o.value_ };
69 }
70 BasicTimelineTick operator- (const BasicTimelineTick &o) const
71 {
72 return BasicTimelineTick{ value_ - o.value_ };
73 }
74 BasicTimelineTick &operator+= (const BasicTimelineTick &o)
75 {
76 value_ += o.value_;
77 return *this;
78 }
79 BasicTimelineTick &operator-= (const BasicTimelineTick &o)
80 {
81 value_ -= o.value_;
82 return *this;
83 }
84 BasicTimelineTick operator- () const { return BasicTimelineTick{ -value_ }; }
85
86 // --- Scalar arithmetic (interpolation helpers) ---
87
89 constexpr double operator/ (const BasicTimelineTick &o) const
90 {
91 return value_ / o.value_;
92 }
93
95 constexpr BasicTimelineTick operator* (double scalar) const
96 {
97 return BasicTimelineTick{ value_ * scalar };
98 }
99
101 friend constexpr BasicTimelineTick
102 operator* (double scalar, const BasicTimelineTick &t)
103 {
104 return BasicTimelineTick{ scalar * t.value_ };
105 }
106
107 // --- Accessors ---
108 Q asQuantity () const { return value_; }
109 double asDouble () const { return value_.in (units::ticks); }
110};
111
114
117using TimelineTickI = BasicTimelineTick<units::tick_t>;
118
126template <typename Q> struct BasicContentTick
127{
128 Q value_{};
129
130 // --- Default special members ---
131 constexpr BasicContentTick () = default;
132 constexpr BasicContentTick (const BasicContentTick &) = default;
133 constexpr BasicContentTick (BasicContentTick &&) noexcept = default;
134 constexpr BasicContentTick &operator= (const BasicContentTick &) = default;
135 constexpr BasicContentTick &
136 operator= (BasicContentTick &&) noexcept = default;
137
139 template <typename Q2>
140 requires std::convertible_to<Q2, Q>
141 constexpr explicit BasicContentTick (Q2 q) : value_ (std::move (q))
142 {
143 }
144
145 // --- Cross-precision constructor (delegates to au) ---
146
148 template <typename Q2>
149 requires (!std::same_as<Q, Q2>) && std::convertible_to<const Q2 &, Q>
150 constexpr BasicContentTick (const BasicContentTick<Q2> &other)
151 : value_ (other.value_)
152 {
153 }
154
155 // --- Comparisons (same type only — prevents cross-domain mixing) ---
156 bool operator== (const BasicContentTick &) const = default;
157 auto operator<=> (const BasicContentTick &) const = default;
158
159 // --- Arithmetic (same type only) ---
160 BasicContentTick operator+ (const BasicContentTick &o) const
161 {
162 return BasicContentTick{ value_ + o.value_ };
163 }
164 BasicContentTick operator- (const BasicContentTick &o) const
165 {
166 return BasicContentTick{ value_ - o.value_ };
167 }
168 BasicContentTick &operator+= (const BasicContentTick &o)
169 {
170 value_ += o.value_;
171 return *this;
172 }
173 BasicContentTick &operator-= (const BasicContentTick &o)
174 {
175 value_ -= o.value_;
176 return *this;
177 }
178 BasicContentTick operator- () const { return BasicContentTick{ -value_ }; }
179
180 // --- Scalar arithmetic (interpolation helpers) ---
181
183 constexpr double operator/ (const BasicContentTick &o) const
184 {
185 return value_ / o.value_;
186 }
187
189 constexpr BasicContentTick operator* (double scalar) const
190 {
191 return BasicContentTick{ value_ * scalar };
192 }
193
195 friend constexpr BasicContentTick
196 operator* (double scalar, const BasicContentTick &t)
197 {
198 return BasicContentTick{ scalar * t.value_ };
199 }
200
201 // --- Accessors ---
202 Q asQuantity () const { return value_; }
203 double asDouble () const { return value_.in (units::ticks); }
204};
205
208
210using ContentTickI = BasicContentTick<units::tick_t>;
211
212// --- Concept and helpers ---
213
214namespace detail
215{
216template <typename> struct is_basic_timeline_tick : std::false_type
217{
218};
219template <typename Q>
220struct is_basic_timeline_tick<BasicTimelineTick<Q>> : std::true_type
221{
222};
223template <typename> struct is_basic_content_tick : std::false_type
224{
225};
226template <typename Q>
227struct is_basic_content_tick<BasicContentTick<Q>> : std::true_type
228{
229};
230}
231
232template <typename T>
233concept TickType =
236
237template <TickType T>
238T
239abs (T t)
240{
241 return t < T{} ? -t : t;
242}
243
244} // namespace zrythm::dsp
245
246// Formatters — write value directly to output buffer, then append domain label.
247// Inherits parse() from fmt::formatter<double> so format specs like {:>10.2f}
248// apply to the numeric part.
249template <typename U>
250struct fmt::formatter<::zrythm::dsp::BasicTimelineTick<U>>
251 : fmt::formatter<double>
252{
253 template <typename FormatContext>
254 constexpr auto
255 format (const ::zrythm::dsp::BasicTimelineTick<U> &t, FormatContext &ctx) const
256 {
257 auto out = fmt::formatter<double>::format (t.asDouble (), ctx);
258 return fmt::format_to (out, " timeline ticks");
259 }
260};
261
262template <typename U>
263struct fmt::formatter<::zrythm::dsp::BasicContentTick<U>> : fmt::formatter<double>
264{
265 template <typename FormatContext>
266 constexpr auto
267 format (const ::zrythm::dsp::BasicContentTick<U> &t, FormatContext &ctx) const
268 {
269 auto out = fmt::formatter<double>::format (t.asDouble (), ctx);
270 return fmt::format_to (out, " content ticks");
271 }
272};
273
274static_assert (fmt::formattable<::zrythm::dsp::TimelineTick>);
275static_assert (fmt::formattable<::zrythm::dsp::ContentTick>);
Positions relative to a clip's data origin (0 = clip start).
Definition tick_types.h:127
constexpr BasicContentTick(const BasicContentTick< Q2 > &other)
Implicit widening (e.g. int→double) — au allows it.
Definition tick_types.h:150
constexpr double operator/(const BasicContentTick &o) const
Dimensionless ratio of two equal-domain quantities (this / o).
Definition tick_types.h:183
constexpr BasicContentTick(Q2 q)
Construct from any au quantity convertible to Q.
Definition tick_types.h:141
constexpr BasicContentTick operator*(double scalar) const
Scale by a dimensionless factor.
Definition tick_types.h:189
Absolute positions on the project's musical timeline.
Definition tick_types.h:33
constexpr double operator/(const BasicTimelineTick &o) const
Dimensionless ratio of two equal-domain quantities (this / o).
Definition tick_types.h:89
constexpr BasicTimelineTick operator*(double scalar) const
Scale by a dimensionless factor.
Definition tick_types.h:95
constexpr BasicTimelineTick(const BasicTimelineTick< Q2 > &other)
Implicit widening (e.g. int→double) — au allows it.
Definition tick_types.h:56
constexpr BasicTimelineTick(Q2 q)
Construct from any au quantity convertible to Q.
Definition tick_types.h:47