From 9aec2a98068a38dca9b09c45116f9cc662bf19b1 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Sat, 17 Mar 2012 00:49:58 +0100 Subject: [PATCH] allow for fractional scaling of time durations implemented as extension to the linear combinations. I decided to use the same "always floor" rule as employed for time quantisation. Moreover, we don't support floating point, only rationals --- src/lib/time/lumitime.cpp | 12 ++++++++++++ src/lib/time/timevalue.hpp | 23 ++++++++++++++++------- tests/lib/time/time-value-test.cpp | 23 +++++++++++++++++++++++ 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/lib/time/lumitime.cpp b/src/lib/time/lumitime.cpp index 82de03645..03218ebb7 100644 --- a/src/lib/time/lumitime.cpp +++ b/src/lib/time/lumitime.cpp @@ -23,12 +23,14 @@ #include "lib/time/timevalue.hpp" #include "lib/time.h" +#include "lib/util-quant.hpp" #include #include #include using std::string; +using util::floordiv; namespace lib { @@ -122,6 +124,16 @@ namespace time { } + Offset + operator* (boost::rational factor, Offset const& o) + { + boost::rational distance (_raw(o)); + distance *= factor; + gavl_time_t microTicks = floordiv (distance.numerator(), distance.denominator()); + return Offset(TimeValue(microTicks)); + } + + /** offset by the given number of frames. */ Offset::Offset (int64_t count, FrameRate const& fps) : TimeValue (count? (count<0? -1:+1) * lumiera_framecount_to_time (::abs(count), fps) diff --git a/src/lib/time/timevalue.hpp b/src/lib/time/timevalue.hpp index 4b429b0ea..b01f295c8 100644 --- a/src/lib/time/timevalue.hpp +++ b/src/lib/time/timevalue.hpp @@ -223,6 +223,13 @@ namespace time { return Offset(distance); } + template + inline Offset + operator* (Offset const& distance, INT factor) + { + return factor*distance; + } + inline Offset operator* (int factor, Offset const& o) { @@ -231,12 +238,12 @@ namespace time { return Offset(distance); } - inline Offset - operator* (Offset const& distance, int factor) - { - return factor*distance; - } + /** stretch offset by a possibly fractional factor */ + Offset + operator* (boost::rational factor, Offset const& o); + + /** flip offset direction */ inline Offset Offset::operator- () const { @@ -365,14 +372,16 @@ namespace time { return Offset(base) + Offset(toAdd); } + template inline Offset - operator* (int factor, Duration const& dur) + operator* (INT factor, Duration const& dur) { return factor * Offset(dur); } + template inline Offset - operator* (Duration const& dur, int factor) + operator* (Duration const& dur, INT factor) { return factor*dur; } diff --git a/tests/lib/time/time-value-test.cpp b/tests/lib/time/time-value-test.cpp index 27656bd44..59d71b7c2 100644 --- a/tests/lib/time/time-value-test.cpp +++ b/tests/lib/time/time-value-test.cpp @@ -76,6 +76,7 @@ namespace test{ buildTimeSpan (ref); compareTimeSpan (Time(ref)); relateTimeIntervals (ref); + verify_fractionalOffset(); } @@ -286,6 +287,28 @@ namespace test{ } + void + verify_fractionalOffset () + { + typedef boost::rational Frac; + + Duration three (TimeValue(3)); // three micro seconds + + Offset o1 = Frac(1,2) * three; + CHECK (o1 > Time::ZERO); + CHECK (o1 == TimeValue(1)); // bias towards the next lower micro grid position + + Offset o2 = -Frac(1,2) * three; + CHECK (o2 < Time::ZERO); + CHECK (o2 == TimeValue(-2)); + + CHECK (three * Frac(1,2) * 2 != three); + CHECK (three *(Frac(1,2) * 2) == three); + // integral arithmetics is precise, + // but not necessarily exact! + } + + void buildTimeSpan (TimeValue org) {