2011-01-06 04:21:18 +01:00
|
|
|
/*
|
|
|
|
|
QuantiserBasics(Test) - a demo quantiser to cover the basic quantiser API
|
|
|
|
|
|
|
|
|
|
Copyright (C) Lumiera.org
|
|
|
|
|
2011, Hermann Vosseler <Ichthyostega@web.de>
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of
|
|
|
|
|
the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
* *****************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "lib/test/run.hpp"
|
2011-01-09 11:41:08 +01:00
|
|
|
#include "lib/test/test-helper.hpp"
|
2011-01-06 04:21:18 +01:00
|
|
|
#include "lib/time/quantiser.hpp"
|
|
|
|
|
#include "lib/util.hpp"
|
2011-01-09 11:41:08 +01:00
|
|
|
#include <cstdlib>
|
2011-01-06 04:21:18 +01:00
|
|
|
|
2011-01-09 11:41:08 +01:00
|
|
|
using lumiera::error::LUMIERA_ERROR_BOTTOM_VALUE;
|
2011-01-06 04:21:18 +01:00
|
|
|
using util::isnil;
|
2011-01-09 11:41:08 +01:00
|
|
|
using std::rand;
|
2011-01-06 04:21:18 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
namespace lib {
|
|
|
|
|
namespace time{
|
|
|
|
|
namespace test{
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
|
|
const uint MAX_FRAMES = 25*500;
|
2011-01-15 14:07:25 +01:00
|
|
|
const uint DIRT_GRAIN = 50;
|
2011-01-06 04:21:18 +01:00
|
|
|
|
2011-03-31 18:43:50 +02:00
|
|
|
const FSecs F25(1,25); // duration of one PAL frame
|
|
|
|
|
|
|
|
|
|
inline Time
|
|
|
|
|
secs (int seconds)
|
|
|
|
|
{
|
|
|
|
|
return Time(FSecs(seconds));
|
|
|
|
|
}
|
2011-01-06 04:21:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-01-09 11:41:08 +01:00
|
|
|
|
2013-10-24 23:06:36 +02:00
|
|
|
/****************************************************//**
|
2011-01-06 04:21:18 +01:00
|
|
|
* @test cover the basic Quantiser API.
|
2011-01-09 11:41:08 +01:00
|
|
|
* This test uses a standalone quantiser implementation
|
|
|
|
|
* to demonstrate and verify the basic behaviour
|
|
|
|
|
* and the usage corner cases of a quantiser.
|
|
|
|
|
*
|
|
|
|
|
* In this most simple form, a quantiser is defined
|
|
|
|
|
* by the time reference point (origin) to use, and
|
|
|
|
|
* the frame rate (grid spacing). For each raw time
|
|
|
|
|
* value, the quantiser yields a time value aligned
|
|
|
|
|
* at the next lower frame bound. Besides that,
|
|
|
|
|
* time values are confined to be within
|
|
|
|
|
* the interval (Time::MIN, Time::Max)
|
|
|
|
|
*
|
|
|
|
|
* @see TimeQuantisation_test
|
2011-01-06 04:21:18 +01:00
|
|
|
*/
|
|
|
|
|
class QuantiserBasics_test : public Test
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
virtual void
|
|
|
|
|
run (Arg)
|
|
|
|
|
{
|
|
|
|
|
checkSimpleQuantisation ();
|
2011-01-08 03:30:10 +01:00
|
|
|
coverQuantisationStandardCases();
|
|
|
|
|
coverQuantisationCornerCases();
|
2011-01-06 04:21:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
checkSimpleQuantisation ()
|
|
|
|
|
{
|
|
|
|
|
FixedFrameQuantiser fixQ(25);
|
|
|
|
|
|
|
|
|
|
uint frames = (rand() % MAX_FRAMES);
|
2011-12-31 06:38:31 +01:00
|
|
|
FSecs dirt = (F25 / (2 + rand() % DIRT_GRAIN));
|
2011-01-06 04:21:18 +01:00
|
|
|
|
2013-11-10 04:17:53 +01:00
|
|
|
Time rawTime = Time(frames*F25) + Duration(dirt); ////////////////TICKET #939 : should better use 64bit base type for FSecs ??
|
2011-01-09 11:41:08 +01:00
|
|
|
|
|
|
|
|
CHECK (Time( frames *F25) <= rawTime);
|
2011-01-06 04:21:18 +01:00
|
|
|
CHECK (Time((frames+1)*F25) > rawTime);
|
|
|
|
|
|
2011-01-06 13:31:13 +01:00
|
|
|
Time quantTime (fixQ.gridAlign (rawTime));
|
2011-01-06 04:21:18 +01:00
|
|
|
|
|
|
|
|
CHECK (Time(frames*F25) == quantTime);
|
|
|
|
|
}
|
2011-01-08 03:30:10 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Test Quantiser
|
|
|
|
|
* allowing to use plain numbers.
|
|
|
|
|
* 1 Frame == 3 micro ticks */
|
|
|
|
|
struct TestQuant
|
|
|
|
|
: FixedFrameQuantiser
|
|
|
|
|
{
|
|
|
|
|
TestQuant (int origin=0)
|
2011-01-09 07:04:20 +01:00
|
|
|
: FixedFrameQuantiser( FrameRate(GAVL_TIME_SCALE, 3 ), TimeValue(origin))
|
2011-01-08 03:30:10 +01:00
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
quant (int testPoint)
|
|
|
|
|
{
|
|
|
|
|
TimeVar quantised = this->gridAlign(TimeValue(testPoint));
|
|
|
|
|
return int(quantised);
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
coverQuantisationStandardCases()
|
|
|
|
|
{
|
|
|
|
|
TestQuant q0;
|
|
|
|
|
TestQuant q1(1);
|
|
|
|
|
|
|
|
|
|
CHECK ( 6 == q0.quant(7) );
|
|
|
|
|
CHECK ( 6 == q0.quant(6) );
|
|
|
|
|
CHECK ( 3 == q0.quant(5) );
|
|
|
|
|
CHECK ( 3 == q0.quant(4) );
|
|
|
|
|
CHECK ( 3 == q0.quant(3) );
|
|
|
|
|
CHECK ( 0 == q0.quant(2) );
|
|
|
|
|
CHECK ( 0 == q0.quant(1) );
|
|
|
|
|
CHECK ( 0 == q0.quant(0) );
|
|
|
|
|
CHECK (-3 == q0.quant(-1));
|
|
|
|
|
CHECK (-3 == q0.quant(-2));
|
|
|
|
|
CHECK (-3 == q0.quant(-3));
|
|
|
|
|
CHECK (-6 == q0.quant(-4));
|
|
|
|
|
|
|
|
|
|
CHECK ( 6 == q1.quant(7) );
|
|
|
|
|
CHECK ( 3 == q1.quant(6) );
|
|
|
|
|
CHECK ( 3 == q1.quant(5) );
|
|
|
|
|
CHECK ( 3 == q1.quant(4) );
|
|
|
|
|
CHECK ( 0 == q1.quant(3) );
|
|
|
|
|
CHECK ( 0 == q1.quant(2) );
|
|
|
|
|
CHECK ( 0 == q1.quant(1) );
|
|
|
|
|
CHECK (-3 == q1.quant(0) );
|
|
|
|
|
CHECK (-3 == q1.quant(-1));
|
|
|
|
|
CHECK (-3 == q1.quant(-2));
|
|
|
|
|
CHECK (-6 == q1.quant(-3));
|
|
|
|
|
CHECK (-6 == q1.quant(-4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
coverQuantisationCornerCases()
|
|
|
|
|
{
|
2011-01-09 11:41:08 +01:00
|
|
|
// origin at lower end of the time range
|
2011-01-08 03:30:10 +01:00
|
|
|
FixedFrameQuantiser case1 (1, Time::MIN);
|
2011-03-31 18:43:50 +02:00
|
|
|
CHECK (secs(0) == case1.gridAlign(Time::MIN ));
|
|
|
|
|
CHECK (secs(0) == case1.gridAlign(Time::MIN +TimeValue(1) ));
|
|
|
|
|
CHECK (secs(1) == case1.gridAlign(Time::MIN +secs(1) ));
|
|
|
|
|
CHECK (Time::MAX -secs(1) > case1.gridAlign( secs(-1) ));
|
|
|
|
|
CHECK (Time::MAX -secs(1) <= case1.gridAlign( secs (0) ));
|
|
|
|
|
CHECK (Time::MAX > case1.gridAlign( secs (0) ));
|
|
|
|
|
CHECK (Time::MAX == case1.gridAlign( secs(+1) ));
|
|
|
|
|
CHECK (Time::MAX == case1.gridAlign( secs(+2) ));
|
2011-01-09 11:41:08 +01:00
|
|
|
|
|
|
|
|
// origin at upper end of the time range
|
|
|
|
|
FixedFrameQuantiser case2 (1, Time::MAX);
|
2011-03-31 18:43:50 +02:00
|
|
|
CHECK (secs( 0) == case2.gridAlign(Time::MAX ));
|
|
|
|
|
CHECK (secs(-1) == case2.gridAlign(Time::MAX -TimeValue(1) )); // note: next lower frame
|
|
|
|
|
CHECK (secs(-1) == case2.gridAlign(Time::MAX -secs(1) )); // i.e. the same as a whole frame down
|
|
|
|
|
CHECK (Time::MIN +secs(1) < case2.gridAlign( secs(+2) ));
|
|
|
|
|
CHECK (Time::MIN +secs(1) >= case2.gridAlign( secs(+1) ));
|
|
|
|
|
CHECK (Time::MIN < case2.gridAlign( secs(+1) ));
|
|
|
|
|
CHECK (Time::MIN == case2.gridAlign( secs( 0) )); // note: because of downward truncating,
|
|
|
|
|
CHECK (Time::MIN == case2.gridAlign( secs(-1) )); // resulting values will already exceed
|
|
|
|
|
CHECK (Time::MIN == case2.gridAlign( secs(-2) )); // allowed range and thus will be clipped
|
2011-01-09 11:41:08 +01:00
|
|
|
|
|
|
|
|
// maximum frame size is half the time range
|
2013-09-21 00:22:36 +02:00
|
|
|
Duration hugeFrame(Time::MAX);
|
2011-01-09 11:41:08 +01:00
|
|
|
FixedFrameQuantiser case3 (hugeFrame);
|
|
|
|
|
CHECK (Time::MIN == case3.gridAlign(Time::MIN ));
|
|
|
|
|
CHECK (Time::MIN == case3.gridAlign(Time::MIN +TimeValue(1) ));
|
2011-03-31 18:43:50 +02:00
|
|
|
CHECK (Time::MIN == case3.gridAlign( secs(-1) ));
|
|
|
|
|
CHECK (TimeValue(0) == case3.gridAlign( secs( 0) ));
|
|
|
|
|
CHECK (TimeValue(0) == case3.gridAlign( secs(+1) ));
|
|
|
|
|
CHECK (TimeValue(0) == case3.gridAlign(Time::MAX -TimeValue(1) ));
|
2011-01-09 11:41:08 +01:00
|
|
|
CHECK (Time::MAX == case3.gridAlign(Time::MAX ));
|
|
|
|
|
|
|
|
|
|
// now displacing this grid by +1sec....
|
2011-03-31 18:43:50 +02:00
|
|
|
FixedFrameQuantiser case4 (hugeFrame, secs(1));
|
2011-01-09 11:41:08 +01:00
|
|
|
CHECK (Time::MIN == case4.gridAlign(Time::MIN ));
|
|
|
|
|
CHECK (Time::MIN == case4.gridAlign(Time::MIN +TimeValue(1) )); // clipped...
|
2011-03-31 18:43:50 +02:00
|
|
|
CHECK (Time::MIN == case4.gridAlign(Time::MIN +secs(1) )); // but now exact (unclipped)
|
|
|
|
|
CHECK (Time::MIN == case4.gridAlign( secs(-1) ));
|
|
|
|
|
CHECK (Time::MIN == case4.gridAlign( secs( 0) ));
|
|
|
|
|
CHECK (TimeValue(0) == case4.gridAlign( secs(+1) )); //.....now exactly the frame number zero
|
|
|
|
|
CHECK (TimeValue(0) == case4.gridAlign(Time::MAX -TimeValue(1) ));
|
|
|
|
|
CHECK (TimeValue(0) == case4.gridAlign(Time::MAX )); //.......still truncated down to frame #0
|
2011-01-09 11:41:08 +01:00
|
|
|
|
|
|
|
|
// larger frames aren't possible
|
2011-03-31 18:43:50 +02:00
|
|
|
Duration not_really_larger(secs(10000) + hugeFrame);
|
2011-01-09 11:41:08 +01:00
|
|
|
CHECK (hugeFrame == not_really_larger);
|
|
|
|
|
|
|
|
|
|
// frame sizes below the time micro grid get trapped
|
|
|
|
|
long subAtomic = 2*GAVL_TIME_SCALE; // too small for this universe...
|
|
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(subAtomic) );
|
|
|
|
|
VERIFY_ERROR (BOTTOM_VALUE, FixedFrameQuantiser quark(Duration (FSecs (1,subAtomic))) );
|
2011-01-08 03:30:10 +01:00
|
|
|
}
|
2011-01-06 04:21:18 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Register this test class... */
|
|
|
|
|
LAUNCHER (QuantiserBasics_test, "unit common");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}}} // namespace lib::time::test
|