summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
authorPaul Davis <paul@linuxaudiosystems.com>2017-09-13 17:12:51 -0400
committerPaul Davis <paul@linuxaudiosystems.com>2017-09-18 11:40:53 -0400
commit176cdecd03c9195d12396c0f04b5c375fb9af32e (patch)
tree5c882af0a4a9119f02d032d5846fc33d1046076f /libs
parent9ea43bd5ad7ea3601fb0bda26094ebca21d97c17 (diff)
extend/fix/improve operator overloads and methods for Timecode::BBT_Time
Diffstat (limited to 'libs')
-rw-r--r--libs/timecode/src/bbt_time.cc6
-rw-r--r--libs/timecode/timecode/bbt_time.h61
2 files changed, 56 insertions, 11 deletions
diff --git a/libs/timecode/src/bbt_time.cc b/libs/timecode/src/bbt_time.cc
index 826f0cd91f..8ee6d1a313 100644
--- a/libs/timecode/src/bbt_time.cc
+++ b/libs/timecode/src/bbt_time.cc
@@ -29,15 +29,17 @@ using namespace Timecode;
1/Nth divisions are integer numbers of ticks.
1920 has many factors, though going up to 3840 gets a couple more.
+
+ This needs to match Evoral::Beats::PPQN
*/
const double BBT_Time::ticks_per_beat = 1920.0;
-BBT_Time::BBT_Time (double dbeats)
+BBT_Offset::BBT_Offset (double dbeats)
{
/* NOTE: this does not construct a BBT time in a canonical form,
in that beats may be a very large number, and bars will
- always be zero.
+ always be zero. Hence ... it's a BBT_Offset
*/
assert (dbeats >= 0);
diff --git a/libs/timecode/timecode/bbt_time.h b/libs/timecode/timecode/bbt_time.h
index b3ba3a6b57..b42ccf741e 100644
--- a/libs/timecode/timecode/bbt_time.h
+++ b/libs/timecode/timecode/bbt_time.h
@@ -22,26 +22,31 @@
#include <ostream>
#include <stdint.h>
#include <iomanip>
+#include <exception>
#include "timecode/visibility.h"
namespace Timecode {
/** Bar, Beat, Tick Time (i.e. Tempo-Based Time) */
-struct LIBTIMECODE_API BBT_Time {
+struct LIBTIMECODE_API BBT_Time
+{
static const double ticks_per_beat;
- uint32_t bars;
- uint32_t beats;
- uint32_t ticks;
+ /* note that it is illegal for BBT_Time to have bars==0 or
+ * beats==0. The "neutral" or "default" value is 1|1|0
+ */
- BBT_Time ()
- : bars (1), beats (1), ticks (0) {}
+ int32_t bars;
+ int32_t beats;
+ int32_t ticks;
- BBT_Time (uint32_t ba, uint32_t be, uint32_t t)
- : bars (ba), beats (be), ticks (t) {}
+ struct IllegalBBTTimeException : public std::exception {
+ virtual const char* what() const throw() { return "illegal BBT time (bars or beats were zero)"; }
+ };
- BBT_Time (double beats);
+ BBT_Time () : bars (1), beats (1), ticks (0) {}
+ BBT_Time (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) { if (!bars || !beats) { throw IllegalBBTTimeException(); } }
bool operator< (const BBT_Time& other) const {
return bars < other.bars ||
@@ -74,6 +79,37 @@ struct LIBTIMECODE_API BBT_Time {
bool operator!= (const BBT_Time& other) const {
return bars != other.bars || beats != other.beats || ticks != other.ticks;
}
+
+ /* it would be nice to provide operator+(BBT_Time const&) and
+ * operator-(BBT_Time const&) but this math requires knowledge of the
+ * meter (time signature) used to define 1 bar, and so cannot be
+ * carried out with only two BBT_Time values.
+ */
+
+ BBT_Time round_to_beat () const { return ticks >= (ticks_per_beat/2) ? BBT_Time (bars, beats+1, 0) : BBT_Time (bars, beats, 0); }
+ BBT_Time round_down_to_beat () const { return BBT_Time (bars, beats, 0); }
+ BBT_Time round_up_to_beat () const { return ticks ? BBT_Time (bars, beats+1, 0) : *this; }
+
+ /* cannot implement round_to_bar() without knowing meter (time
+ * signature) information.
+ */
+};
+
+struct LIBTIMECODE_API BBT_Offset
+{
+ int32_t bars;
+ int32_t beats;
+ int32_t ticks;
+
+ /* this is a variant for which bars==0 and/or beats==0 is legal. It
+ * represents an offset from a given BBT_Time and is used when doing
+ * add/subtract operations on a BBT_Time.
+ */
+
+ BBT_Offset () : bars (0), beats (0), ticks (0) {}
+ BBT_Offset (int32_t ba, uint32_t be, uint32_t t) : bars (ba), beats (be), ticks (t) {}
+ BBT_Offset (BBT_Time const & bbt) : bars (bbt.bars), beats (bbt.beats), ticks (bbt.ticks) {}
+ BBT_Offset (double beats);
};
}
@@ -86,6 +122,13 @@ operator<< (std::ostream& o, const Timecode::BBT_Time& bbt)
}
inline std::ostream&
+operator<< (std::ostream& o, const Timecode::BBT_Offset& bbt)
+{
+ o << bbt.bars << '|' << bbt.beats << '|' << bbt.ticks;
+ return o;
+}
+
+inline std::ostream&
print_padded (std::ostream& o, const Timecode::BBT_Time& bbt)
{
o << std::setfill ('0') << std::right