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/link/Beats.hpp>
23 #include <chrono>
24 
25 namespace ableton
26 {
27 namespace link
28 {
29 
30 struct Tempo : std::tuple<double>
31 {
32   Tempo() = default;
33 
34   // Beats per minute
Tempoableton::link::Tempo35   explicit Tempo(const double bpm)
36     : std::tuple<double>(bpm)
37   {
38   }
39 
Tempoableton::link::Tempo40   Tempo(const std::chrono::microseconds microsPerBeat)
41     : std::tuple<double>(60. * 1e6 / microsPerBeat.count())
42   {
43   }
44 
bpmableton::link::Tempo45   double bpm() const
46   {
47     return std::get<0>(*this);
48   }
49 
microsPerBeatableton::link::Tempo50   std::chrono::microseconds microsPerBeat() const
51   {
52     return std::chrono::microseconds{llround(60. * 1e6 / bpm())};
53   }
54 
55   // Given the tempo, convert a time to a beat value
microsToBeatsableton::link::Tempo56   Beats microsToBeats(const std::chrono::microseconds micros) const
57   {
58     return Beats{micros.count() / static_cast<double>(microsPerBeat().count())};
59   }
60 
61   // Given the tempo, convert a beat to a time value
beatsToMicrosableton::link::Tempo62   std::chrono::microseconds beatsToMicros(const Beats beats) const
63   {
64     return std::chrono::microseconds{llround(beats.floating() * microsPerBeat().count())};
65   }
66 
67   // Model the NetworkByteStreamSerializable concept
sizeInByteStream(const Tempo tempo)68   friend std::uint32_t sizeInByteStream(const Tempo tempo)
69   {
70     return discovery::sizeInByteStream(tempo.microsPerBeat());
71   }
72 
73   template <typename It>
toNetworkByteStream(const Tempo tempo,It out)74   friend It toNetworkByteStream(const Tempo tempo, It out)
75   {
76     return discovery::toNetworkByteStream(tempo.microsPerBeat(), std::move(out));
77   }
78 
79   template <typename It>
fromNetworkByteStreamableton::link::Tempo80   static std::pair<Tempo, It> fromNetworkByteStream(It begin, It end)
81   {
82     auto result =
83       discovery::Deserialize<std::chrono::microseconds>::fromNetworkByteStream(
84         std::move(begin), std::move(end));
85     return std::make_pair(Tempo{std::move(result.first)}, std::move(result.second));
86   }
87 };
88 
89 } // namespace link
90 } // namespace ableton
91