Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
tick.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <compare>
4#include <cstdint>
5#include <limits>
6
7namespace pulp::timebase {
8
9namespace detail {
10
11constexpr std::int64_t saturating_add(std::int64_t lhs, std::int64_t rhs) noexcept {
12 if (rhs > 0 && lhs > std::numeric_limits<std::int64_t>::max() - rhs)
13 return std::numeric_limits<std::int64_t>::max();
14 if (rhs < 0 && lhs < std::numeric_limits<std::int64_t>::min() - rhs)
15 return std::numeric_limits<std::int64_t>::min();
16 return lhs + rhs;
17}
18
19constexpr std::int64_t saturating_subtract(std::int64_t lhs, std::int64_t rhs) noexcept {
20 if (rhs > 0 && lhs < std::numeric_limits<std::int64_t>::min() + rhs)
21 return std::numeric_limits<std::int64_t>::min();
22 if (rhs < 0 && lhs > std::numeric_limits<std::int64_t>::max() + rhs)
23 return std::numeric_limits<std::int64_t>::max();
24 return lhs - rhs;
25}
26
27constexpr std::int64_t saturating_multiply(std::int64_t lhs, std::int64_t rhs) noexcept {
28 constexpr std::int64_t max = std::numeric_limits<std::int64_t>::max();
29 constexpr std::int64_t min = std::numeric_limits<std::int64_t>::min();
30 if (lhs == 0 || rhs == 0)
31 return 0;
32 // Identity and negation are special-cased so the division tests below can
33 // assume |operand| >= 2, where the truncating division is exact enough to
34 // decide overflow. min has no positive counterpart, so negating it rails.
35 if (lhs == 1)
36 return rhs;
37 if (rhs == 1)
38 return lhs;
39 if (lhs == -1)
40 return (rhs == min) ? max : -rhs;
41 if (rhs == -1)
42 return (lhs == min) ? max : -lhs;
43 if ((lhs < 0) != (rhs < 0)) {
44 if (lhs > 0 ? (rhs < min / lhs) : (lhs < min / rhs))
45 return min;
46 } else if (lhs > 0 ? (lhs > max / rhs) : (lhs < max / rhs)) {
47 return max;
48 }
49 return lhs * rhs;
50}
51
52} // namespace detail
53
54inline constexpr std::int64_t kTicksPerQuarter = 705'600;
55
57 std::int64_t value = 0;
58 constexpr auto operator<=>(const TickDuration&) const = default;
59};
60
62 std::int64_t value = 0;
63 constexpr auto operator<=>(const TickPosition&) const = default;
64};
65
66// Musical position on the transport's non-looping clock. Timeline positions
67// may seek or wrap; MonotonicBeat is advanced independently so scheduled
68// intents such as "launch at the next bar" retain a stable clock domain.
69// The transport owns that advancement policy. The timebase module supplies
70// the strong type so a looping TickPosition cannot be passed accidentally.
73 constexpr auto operator<=>(const MonotonicBeat&) const = default;
74};
75
76// Position and duration arithmetic is total over the signed 64-bit domain:
77// results that exceed it clamp to the nearest endpoint.
78
79constexpr TickPosition operator+(TickPosition position, TickDuration duration) noexcept {
80 return {detail::saturating_add(position.value, duration.value)};
81}
82
83constexpr TickPosition operator-(TickPosition position, TickDuration duration) noexcept {
84 return {detail::saturating_subtract(position.value, duration.value)};
85}
86
87constexpr TickDuration operator-(TickPosition lhs, TickPosition rhs) noexcept {
88 return {detail::saturating_subtract(lhs.value, rhs.value)};
89}
90
91constexpr MonotonicBeat operator+(MonotonicBeat beat, TickDuration duration) noexcept {
92 return {{detail::saturating_add(beat.position.value, duration.value)}};
93}
94
95constexpr MonotonicBeat operator-(MonotonicBeat beat, TickDuration duration) noexcept {
96 return {{detail::saturating_subtract(beat.position.value, duration.value)}};
97}
98
99constexpr TickDuration operator-(MonotonicBeat lhs, MonotonicBeat rhs) noexcept {
100 return {detail::saturating_subtract(lhs.position.value, rhs.position.value)};
101}
102
103} // namespace pulp::timebase
Definition beat_division.hpp:52
constexpr std::int64_t saturating_multiply(std::int64_t lhs, std::int64_t rhs) noexcept
Definition tick.hpp:27
constexpr std::int64_t saturating_add(std::int64_t lhs, std::int64_t rhs) noexcept
Definition tick.hpp:11
constexpr std::int64_t saturating_subtract(std::int64_t lhs, std::int64_t rhs) noexcept
Definition tick.hpp:19
Definition beat_division.hpp:11
constexpr std::int64_t kTicksPerQuarter
Definition tick.hpp:54
constexpr TickPosition operator+(TickPosition position, TickDuration duration) noexcept
Definition tick.hpp:79
constexpr TickPosition operator-(TickPosition position, TickDuration duration) noexcept
Definition tick.hpp:83
Definition tick.hpp:71
constexpr auto operator<=>(const MonotonicBeat &) const =default
TickPosition position
Definition tick.hpp:72
Definition tick.hpp:56
std::int64_t value
Definition tick.hpp:57
constexpr auto operator<=>(const TickDuration &) const =default
Definition tick.hpp:61
std::int64_t value
Definition tick.hpp:62
constexpr auto operator<=>(const TickPosition &) const =default