Zrythm v2.0.0-alpha.1
a highly automated and intuitive digital audio workstation
Loading...
Searching...
No Matches
units.h
1// SPDX-FileCopyrightText: © 2025-2026 Alexandros Theodotou <alex@zrythm.org>
2// SPDX-License-Identifier: LicenseRef-ZrythmLicense
3
4#pragma once
5
6#include <au/au.hh>
7#include <au/units/minutes.hh>
8#include <fmt/format.h>
9
10namespace zrythm::units
11{
12
13// Define base dimensions using unique indices based on Unix epoch timestamps
14// for uniqueness
15struct SampleBaseDim : au::base_dim::BaseDimension<1737814550>
16{
17};
18struct TickBaseDim : au::base_dim::BaseDimension<1737814551>
19{
20};
21struct ChannelBaseDim : au::base_dim::BaseDimension<1777738085>
22{
23};
24
25// Define sample unit with its own dimension
26struct Sample : au::UnitImpl<au::Dimension<SampleBaseDim>>
27{
28 static constexpr const char label[] = "sample";
29};
30constexpr auto sample = au::SingularNameFor<Sample>{};
31constexpr auto samples = au::QuantityMaker<Sample>{};
32
33// Define sample quantity types
34using sample_t = au::QuantityI64<Sample>;
35using sample_u32_t = au::QuantityU32<Sample>;
36using sample_u64_t = au::QuantityU64<Sample>;
37using precise_sample_t = au::QuantityD<Sample>;
38
39// Define tick unit with its own dimension
40struct Tick : au::UnitImpl<au::Dimension<TickBaseDim>>
41{
42 static constexpr const char label[] = "tick";
43};
44constexpr auto tick = au::SingularNameFor<Tick>{};
45constexpr auto ticks = au::QuantityMaker<Tick>{};
46
47// Define tick quantity types
48using tick_t = au::QuantityI64<Tick>;
49using precise_tick_t = au::QuantityD<Tick>;
50
51// Define channel count unit with its own dimension
52struct ChannelCount : au::UnitImpl<au::Dimension<ChannelBaseDim>>
53{
54 static constexpr const char label[] = "channel";
55};
56constexpr auto channel = au::SingularNameFor<ChannelCount>{};
57constexpr auto channels = au::QuantityMaker<ChannelCount>{};
58
59// Define channel count quantity types
60using channel_count_t = au::Quantity<ChannelCount, uint8_t>;
61
62// Define PPQ constant (960 ticks per quarter note)
63constexpr tick_t PPQ = ticks (960);
64
65// Define quarter_note unit as 960 ticks using unit expression
66struct QuarterNote : decltype (Tick{} * au::mag<PPQ.in (units::ticks)> ())
67{
68 static constexpr const char label[] = "quarterNote";
69};
70constexpr auto quarter_note = au::SingularNameFor<QuarterNote>{};
71constexpr auto quarter_notes = au::QuantityMaker<QuarterNote>{};
72
73// Define BPM as quarter notes per minute (compound unit in TickDim × TimeDim⁻¹).
74//
75// In MIDI and virtually all DAWs, "BPM" means quarter notes per minute,
76// independent of time signature. The time signature's denominator only affects
77// the bar:beat grid (e.g. 4/4 → 4 quarter-note beats per bar, 6/8 → 2
78// dotted-quarter beats per bar) but never changes the wall-clock tempo. So a
79// single "quarter note" beat unit covers all practical cases without needing a
80// separate beat_type parameter.
81struct BPM : decltype (QuarterNote{} / au::Minutes{})
82{
83 static constexpr const char label[] = "bpm";
84};
85constexpr auto bpm = au::QuantityMaker<BPM>{};
86using bpm_t = au::QuantityD<BPM>;
87
88// Define sample rate as a compound unit (samples per second)
89using SampleRate = decltype (Sample{} / au::Seconds{});
90constexpr auto sample_rate = samples / au::second;
91using sample_rate_t = au::QuantityI<SampleRate>;
92using precise_sample_rate_t = au::QuantityD<SampleRate>;
93
94// Define precise second using Au's built-in seconds
95constexpr auto seconds = au::seconds;
96using precise_second_t = au::QuantityD<au::Seconds>;
97} // namespace zrythm::units
98
99// Formatter for Au quantities
100template <typename U, typename R>
101struct fmt::formatter<::au::Quantity<U, R>>
102 : ::au::QuantityFormatter<U, R, ::fmt::formatter>
103{
104};