1 /* Copyright 2016, Ableton AG, Berlin. All rights reserved.
2  *
3  *  This program is free software: you can redistribute it and/or modify
4  *  it under the terms of the GNU General Public License as published by
5  *  the Free Software Foundation, either version 2 of the License, or
6  *  (at your option) any later version.
7  *
8  *  This program is distributed in the hope that it will be useful,
9  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  *  GNU General Public License for more details.
12  *
13  *  You should have received a copy of the GNU General Public License
14  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  *  If you would like to incorporate Link into a proprietary software application,
17  *  please contact <link-devs@ableton.com>.
18  */
19 
20 #pragma once
21 
22 #include <ableton/discovery/NetworkByteStreamSerializable.hpp>
23 #include <cmath>
24 #include <cstdint>
25 #include <tuple>
26 
27 namespace ableton
28 {
29 namespace link
30 {
31 
32 struct Beats : std::tuple<std::int64_t>
33 {
34   Beats() = default;
35 
Beatsableton::link::Beats36   explicit Beats(const double beats)
37     : std::tuple<std::int64_t>(llround(beats * 1e6))
38   {
39   }
40 
Beatsableton::link::Beats41   explicit Beats(const std::int64_t microBeats)
42     : std::tuple<std::int64_t>(microBeats)
43   {
44   }
45 
floatingableton::link::Beats46   double floating() const
47   {
48     return microBeats() / 1e6;
49   }
50 
microBeatsableton::link::Beats51   std::int64_t microBeats() const
52   {
53     return std::get<0>(*this);
54   }
55 
operator -ableton::link::Beats56   Beats operator-() const
57   {
58     return Beats{-microBeats()};
59   }
60 
abs(const Beats b)61   friend Beats abs(const Beats b)
62   {
63     return Beats{std::abs(b.microBeats())};
64   }
65 
operator +(const Beats lhs,const Beats rhs)66   friend Beats operator+(const Beats lhs, const Beats rhs)
67   {
68     return Beats{lhs.microBeats() + rhs.microBeats()};
69   }
70 
operator -(const Beats lhs,const Beats rhs)71   friend Beats operator-(const Beats lhs, const Beats rhs)
72   {
73     return Beats{lhs.microBeats() - rhs.microBeats()};
74   }
75 
operator %(const Beats lhs,const Beats rhs)76   friend Beats operator%(const Beats lhs, const Beats rhs)
77   {
78     return rhs == Beats{0.} ? Beats{0.} : Beats{lhs.microBeats() % rhs.microBeats()};
79   }
80 
81   // Model the NetworkByteStreamSerializable concept
sizeInByteStream(const Beats beats)82   friend std::uint32_t sizeInByteStream(const Beats beats)
83   {
84     return discovery::sizeInByteStream(beats.microBeats());
85   }
86 
87   template <typename It>
toNetworkByteStream(const Beats beats,It out)88   friend It toNetworkByteStream(const Beats beats, It out)
89   {
90     return discovery::toNetworkByteStream(beats.microBeats(), std::move(out));
91   }
92 
93   template <typename It>
fromNetworkByteStreamableton::link::Beats94   static std::pair<Beats, It> fromNetworkByteStream(It begin, It end)
95   {
96     auto result = discovery::Deserialize<std::int64_t>::fromNetworkByteStream(
97       std::move(begin), std::move(end));
98     return std::make_pair(Beats{result.first}, std::move(result.second));
99   }
100 };
101 
102 } // namespace link
103 } // namespace ableton
104