crafting a integer scale wrapping util, for timecode conversions
This commit is contained in:
parent
e1c025778b
commit
05383ea44a
7 changed files with 218 additions and 39 deletions
|
|
@ -85,7 +85,7 @@ extern "C" { /* ===================== C interface ======================== */
|
|||
#endif
|
||||
|
||||
#define NTSC_DROP_FRAME_FPS 29.97
|
||||
/* TODO: replace this by lib/time/FrameRate::NTSC */
|
||||
/* TODO: replace this by lib::time::FrameRate::NTSC */
|
||||
|
||||
/**
|
||||
* Formats a time value in H:MM:SS.mmm format into a temporary buffer.
|
||||
|
|
|
|||
|
|
@ -255,6 +255,7 @@ namespace time {
|
|||
void
|
||||
operator= (NUM n)
|
||||
{
|
||||
if (n == value_) return;
|
||||
NUM changedValue = mutator(n);
|
||||
this->setValueRaw (changedValue);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,8 +59,9 @@ namespace time {
|
|||
}
|
||||
|
||||
|
||||
/** build up a frame count
|
||||
* by quantising the given time value
|
||||
/** build up a SMPTE timecode
|
||||
* by quantising the given time value and then splitting it
|
||||
* into hours, minutes, seconds and frame offset
|
||||
*/
|
||||
void
|
||||
Smpte::rebuild (SmpteTC& tc, QuantR quantiser, TimeValue const& rawTime)
|
||||
|
|
@ -69,7 +70,8 @@ namespace time {
|
|||
UNIMPLEMENTED("build smpte components from raw time");
|
||||
}
|
||||
|
||||
/** calculate the time point denoted by this frame count */
|
||||
/** calculate the time point denoted by this SMPTE timecode,
|
||||
* by summing up the timecode's components */
|
||||
TimeValue
|
||||
Smpte::evaluate (SmpteTC const& tc, QuantR quantiser)
|
||||
{
|
||||
|
|
@ -79,6 +81,38 @@ namespace time {
|
|||
|
||||
}
|
||||
|
||||
namespace { // Timecode implementation details
|
||||
|
||||
|
||||
int
|
||||
wrapFrames (SmpteTC& thisTC, int rawFrames)
|
||||
{
|
||||
int fps = 25; ////////////////////////////////TODO outch
|
||||
thisTC.secs += rawFrames / fps;
|
||||
return rawFrames % fps;
|
||||
//////////////////////////////////TODO need floorwrap-util
|
||||
}
|
||||
|
||||
int
|
||||
wrapSeconds (SmpteTC& thisTC, int rawSecs)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
wrapMinutes (SmpteTC& thisTC, int rawMins)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
wrapHours (SmpteTC& thisTC, int rawHours)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}//(End)implementation details
|
||||
|
||||
|
||||
/** */
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
// 1/10 - can we determine at compile time the presence of a certain function (for duck-typing)?
|
||||
// 4/10 - pretty printing STL containers with python enabled GDB?
|
||||
// 1/11 - exploring numeric limits
|
||||
// 1/11 - integer floor and wrap operation(s)
|
||||
|
||||
|
||||
//#include <nobug.h>
|
||||
|
|
@ -38,31 +39,24 @@ using std::string;
|
|||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
long
|
||||
floordiv (long num, long den)
|
||||
{
|
||||
if (0 < (num^den))
|
||||
return num/den;
|
||||
else
|
||||
{
|
||||
ldiv_t res = ldiv(num,den);
|
||||
return (res.rem)? res.quot-1
|
||||
: res.quot;
|
||||
}
|
||||
}
|
||||
|
||||
long
|
||||
floordiv2 (long num, long den)
|
||||
{
|
||||
ldiv_t res = ldiv(num,den);
|
||||
return (0 >= res.quot && res.rem)? res.quot-1
|
||||
: res.quot;
|
||||
}
|
||||
div_t
|
||||
floorwrap (int num, int den)
|
||||
{
|
||||
div_t res = div (num,den);
|
||||
if (0 > (num^den) && res.rem)
|
||||
{ // wrap similar to floor()
|
||||
--res.quot;
|
||||
res.rem = den - (-res.rem);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void
|
||||
checkDiv(int lhs, int rhs)
|
||||
{
|
||||
cout << format ("%f / %f = %f \tfloor=%f floordiv=%f \n") % lhs % rhs % (lhs / rhs) % floor(double(lhs)/rhs) % floordiv2(lhs,rhs);
|
||||
div_t wrap = floorwrap(lhs,rhs);
|
||||
cout << format ("%2d / %2d = %2d %% = % d \tfloor=%6.2f wrap = (%2d, %2d) \n")
|
||||
% lhs % rhs % (lhs/rhs) % (lhs%rhs) % floor(double(lhs)/rhs) % wrap.quot % wrap.rem;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -87,17 +81,6 @@ main (int, char**)
|
|||
checkDiv (-1,4);
|
||||
checkDiv (-1,-4);
|
||||
|
||||
|
||||
|
||||
int64_t muks = std::numeric_limits<int64_t>::max();
|
||||
muks /= 30;
|
||||
double murks(muks);
|
||||
|
||||
cout << format("%f // %f || %g \n") % muks % murks % std::numeric_limits<double>::epsilon();
|
||||
|
||||
int64_t glucks = murks;
|
||||
cout << glucks <<endl;
|
||||
|
||||
cout << "\n.gulp.\n";
|
||||
|
||||
return 0;
|
||||
|
|
|
|||
|
|
@ -1094,6 +1094,36 @@ return: 0
|
|||
END
|
||||
|
||||
|
||||
PLANNED "integer scale wrapping utility" UtilFloorwrap_test <<END
|
||||
out-lit: 12 / 4 = 3 % = 0 floor= 3.0 wrap = ( 3, 0)
|
||||
out-lit: 11 / 4 = 2 % = 3 floor= 2.0 wrap = ( 2, 3)
|
||||
out-lit: 10 / 4 = 2 % = 2 floor= 2.0 wrap = ( 2, 2)
|
||||
out-lit: 9 / 4 = 2 % = 1 floor= 2.0 wrap = ( 2, 1)
|
||||
out-lit: 8 / 4 = 2 % = 0 floor= 2.0 wrap = ( 2, 0)
|
||||
out-lit: 7 / 4 = 1 % = 3 floor= 1.0 wrap = ( 1, 3)
|
||||
out-lit: 6 / 4 = 1 % = 2 floor= 1.0 wrap = ( 1, 2)
|
||||
out-lit: 5 / 4 = 1 % = 1 floor= 1.0 wrap = ( 1, 1)
|
||||
out-lit: 4 / 4 = 1 % = 0 floor= 1.0 wrap = ( 1, 0)
|
||||
out-lit: 3 / 4 = 0 % = 3 floor= 0.0 wrap = ( 0, 3)
|
||||
out-lit: 2 / 4 = 0 % = 2 floor= 0.0 wrap = ( 0, 2)
|
||||
out-lit: 1 / 4 = 0 % = 1 floor= 0.0 wrap = ( 0, 1)
|
||||
out-lit: 0 / 4 = 0 % = 0 floor= 0.0 wrap = ( 0, 0)
|
||||
out-lit: -1 / 4 = 0 % =-1 floor=-1.0 wrap = (-1, 3)
|
||||
out-lit: -2 / 4 = 0 % =-2 floor=-1.0 wrap = (-1, 2)
|
||||
out-lit: -3 / 4 = 0 % =-3 floor=-1.0 wrap = (-1, 1)
|
||||
out-lit: -4 / 4 =-1 % = 0 floor=-1.0 wrap = (-1, 0)
|
||||
out-lit: -5 / 4 =-1 % =-1 floor=-2.0 wrap = (-2, 3)
|
||||
out-lit: -6 / 4 =-1 % =-2 floor=-2.0 wrap = (-2, 2)
|
||||
out-lit: -7 / 4 =-1 % =-3 floor=-2.0 wrap = (-2, 1)
|
||||
out-lit: -8 / 4 =-2 % = 0 floor=-2.0 wrap = (-2, 0)
|
||||
out-lit: -9 / 4 =-2 % =-1 floor=-3.0 wrap = (-3, 3)
|
||||
out-lit:-10 / 4 =-2 % =-2 floor=-3.0 wrap = (-3, 2)
|
||||
out-lit:-11 / 4 =-2 % =-3 floor=-3.0 wrap = (-3, 1)
|
||||
out-lit:-12 / 4 =-3 % = 0 floor=-3.0 wrap = (-3, 0)
|
||||
return: 0
|
||||
END
|
||||
|
||||
|
||||
TEST "for-each operations" UtilForeach_test 10 <<END
|
||||
out: ---:check_foreach_plain
|
||||
out: :10:9:8:7:6:5:4:3:2:1
|
||||
|
|
|
|||
131
tests/lib/util-floorwrap-test.cpp
Normal file
131
tests/lib/util-floorwrap-test.cpp
Normal file
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
UtilFloorwrap(Test) - verify integer scale remainder wrapping
|
||||
|
||||
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"
|
||||
#include "lib/util.hpp"
|
||||
|
||||
#include <cmath>
|
||||
//#include <vector>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
using ::Test;
|
||||
using std::cout;
|
||||
//using std::rand;
|
||||
using boost::format;
|
||||
|
||||
|
||||
namespace util {
|
||||
namespace test {
|
||||
|
||||
|
||||
|
||||
namespace{ // Test data and operations
|
||||
|
||||
div_t
|
||||
floorwrap (int num, int den)
|
||||
{
|
||||
div_t res = div (num,den);
|
||||
if (0 > (num^den) && res.rem)
|
||||
{ // wrap similar to floor()
|
||||
--res.quot;
|
||||
res.rem = den - (-res.rem);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
showWrap (int val, int scale)
|
||||
{
|
||||
div_t wrap = floorwrap(val,scale);
|
||||
cout << format ("% 3d /% 1d =% 1d %% =% d floor=% 4.1f wrap = (%2d,%2d) \n")
|
||||
% val % scale % (val/scale)
|
||||
% (val%scale) % floor(double(val)/scale)
|
||||
% wrap.quot % wrap.rem;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // (End) test data and operations
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* @test Evaluate a custom built integer floor function.
|
||||
* This function is crucial for Lumiera's rule of quantisation
|
||||
* of time values into frame intervals. This rule requires time
|
||||
* points to be rounded towards the next lower frame border always,
|
||||
* irrespective of the relation to the actual time origin.
|
||||
* Contrast this to the built-in integer division operator, which
|
||||
* truncates towards zero.
|
||||
*
|
||||
* @note if invoked with an non empty parameter, this test performs
|
||||
* some interesting timing comparisons, which initially were
|
||||
* used to tweak the implementation a bit.
|
||||
* @see util.hpp
|
||||
* @see QuantiserBasics_test
|
||||
*/
|
||||
class UtilFloorwrap_test : public Test
|
||||
{
|
||||
|
||||
virtual void
|
||||
run (Arg arg)
|
||||
{
|
||||
showWrap ( 12,4);
|
||||
showWrap ( 11,4);
|
||||
showWrap ( 10,4);
|
||||
showWrap ( 9,4);
|
||||
showWrap ( 8,4);
|
||||
showWrap ( 7,4);
|
||||
showWrap ( 6,4);
|
||||
showWrap ( 5,4);
|
||||
showWrap ( 4,4);
|
||||
showWrap ( 3,4);
|
||||
showWrap ( 2,4);
|
||||
showWrap ( 1,4);
|
||||
showWrap ( 0,4);
|
||||
showWrap (- 1,4);
|
||||
showWrap (- 2,4);
|
||||
showWrap (- 3,4);
|
||||
showWrap (- 4,4);
|
||||
showWrap (- 5,4);
|
||||
showWrap (- 6,4);
|
||||
showWrap (- 7,4);
|
||||
showWrap (- 8,4);
|
||||
showWrap (- 9,4);
|
||||
showWrap (-10,4);
|
||||
showWrap (-11,4);
|
||||
showWrap (-12,4);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
LAUNCHER (UtilFloorwrap_test, "unit common");
|
||||
|
||||
|
||||
}} // namespace util::test
|
||||
|
|
@ -6746,7 +6746,7 @@ Question is: how fine grained and configurable needs this to be?
|
|||
|
||||
</pre>
|
||||
</div>
|
||||
<div title="TimecodeFormat" modifier="Ichthyostega" modified="201101151404" created="201101100308" tags="Player spec discuss draft" changecount="17">
|
||||
<div title="TimecodeFormat" modifier="Ichthyostega" modified="201101190857" created="201101100308" tags="Player spec discuss draft" changecount="18">
|
||||
<pre>The handling of [[Timecode]] is closely related to [[time representation and quantisation|TimeQuant]]. In fact, these two topics blend into one another. Time will be quantised into a //grid,// but this grid only makes sense when linked to a externally relevant meaning and representation, which is the Timecode. But a timecode value also denotes a specific point in time -- performing operations on a timecode is equivalent to manipulating a quantised time value.
|
||||
|
||||
!Problem of dependencies
|
||||
|
|
@ -6771,9 +6771,9 @@ And last but not least, it is possible to get a new ~TimeValue, reflecting the c
|
|||
!!{{red{WIP 1/11}}}design tasks
|
||||
* @@color:green;✔@@ find out about the connection to the MetaAsset &rarr; [[Advice]]
|
||||
* @@color:green;✔@@ determine the primitives which need to be on the //effective quantiser API.//
|
||||
* find out how a format can address the individual components it's comprised of
|
||||
* @@color:green;✔@@ find out how a format can address the individual components it's comprised of &rarr; direct access by concrete type
|
||||
* @@color:green;✔@@ decide how a concrete TC value can refer to his quantiser &rarr; always using smart-ptr
|
||||
* maybe coin a //value handle// -- to tie the three required parts together
|
||||
* @@color:red;??@@ maybe coin a //value handle// -- to tie the three required parts together
|
||||
</pre>
|
||||
</div>
|
||||
<div title="Timeline" modifier="Ichthyostega" modified="201011220126" created="200706250721" tags="def" changecount="21">
|
||||
|
|
|
|||
Loading…
Reference in a new issue