Library: rectify confusingly named function on the Grid API

The APIs for time quantisation were drafted in an early stage of the project
and then never followed-up. Especially Grid::gridAlign has no
real-world usage yet, and is only massaged in some tests.

When looking at QuantiserBasics_test, I was puzzled and led astray,
since this function suggests to materialise a continuous time into
a quantised time -- which it doesn't (there is another dedicated
function Quantiser::materialise() to that end); so, without engaging
into the discussion if this function is of any use, I'll hereby
choose a name better reflecting what it does.
This commit is contained in:
Fischlurch 2022-12-05 01:05:23 +01:00
parent 50c602ec3f
commit 13adc56f34
7 changed files with 118 additions and 90 deletions

View file

@ -111,7 +111,7 @@ int64_t
lumiera_quantise_frames_fps (gavl_time_t time, gavl_time_t origin, uint framerate);
/**
* Similar to #lumiera_quantise_frames, but returns a grid aligned \em time value
* Similar to #lumiera_quantise_frames, but returns a grid aligned _relative time._
* @return time of start of the grid interval containing the given time,
* but measured relative to the origin
* @warning because the resulting value needs to be limited to fit into a 64bit long,

View file

@ -71,7 +71,7 @@ namespace time {
virtual FrameCnt gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue gridLocal (TimeValue const& raw) const =0;
virtual TimeValue timeOf (FrameCnt gridPoint) const =0;
virtual TimeValue timeOf (FSecs gridTime, int=0) const =0;
};

View file

@ -114,25 +114,6 @@ namespace time {
/** alignment to a simple fixed size grid.
* The actual calculation first determines the number
* of the grid interval containing the given rawTime,
* then followed by multiplying this interval number
* with the grid spacing.
* @return time of the start point of the grid interval
* containing the rawTime, relative to the origin
* of the time scale used by this quantiser.
* @warning returned time values are limited by the
* valid range of lumiera::Time
* @see #lumiera_quantise_time
*/
TimeValue
FixedFrameQuantiser::gridAlign (TimeValue const& rawTime) const
{
return TimeValue (lumiera_quantise_time (_raw(rawTime), _raw(origin_), _raw(raster_)));
}
/** grid quantisation (alignment).
* Determine the next lower grid interval start point,
* using a simple constant spaced time grid defined by
@ -148,6 +129,25 @@ namespace time {
}
/** transform into the local time scale grid aligned.
* The actual calculation first determines the number
* of the grid interval containing the given rawTime,
* then followed by multiplying this interval number
* with the grid spacing.
* @return time of the start point of the grid interval
* containing the rawTime, _relative to the origin_
* of the time scale used by this quantiser.
* @warning returned time values are limited by the
* valid range of lumiera::Time
* @see #lumiera_quantise_time
*/
TimeValue
FixedFrameQuantiser::gridLocal (TimeValue const& rawTime) const
{
return TimeValue (lumiera_quantise_time (_raw(rawTime), _raw(origin_), _raw(raster_)));
}
/** calculate time value of a grid interval (frame) start point
* @return time point measured in Lumiera internal time
* @warning returned time values are limited by the

View file

@ -123,7 +123,7 @@ namespace time {
//------Grid-API----------------------------------------------
virtual FrameCnt gridPoint (TimeValue const& raw) const =0;
virtual TimeValue gridAlign (TimeValue const& raw) const =0;
virtual TimeValue gridLocal (TimeValue const& raw) const =0;
virtual TimeValue timeOf (FrameCnt gridPoint) const =0;
virtual TimeValue timeOf (FSecs, int =0) const =0;
};
@ -152,7 +152,7 @@ namespace time {
FixedFrameQuantiser (Duration const& frame_duration, TimeValue referencePoint =TimeValue(0));
FrameCnt gridPoint (TimeValue const&) const;
TimeValue gridAlign (TimeValue const&) const;
TimeValue gridLocal (TimeValue const&) const;
TimeValue timeOf (FrameCnt gridPoint) const;
TimeValue timeOf (FSecs, int =0) const;

View file

@ -99,7 +99,7 @@ namespace test{
CHECK (Time( frames *F25) <= rawTime);
CHECK (Time((frames+1)*F25) > rawTime);
Time quantTime (fixQ.gridAlign (rawTime));
Time quantTime (fixQ.gridLocal (rawTime));
CHECK (Time(frames*F25) == quantTime);
}
@ -118,7 +118,7 @@ namespace test{
int
quant (int testPoint)
{
TimeVar quantised = this->gridAlign(TimeValue(testPoint));
TimeVar quantised = this->gridLocal(TimeValue(testPoint));
return int(quantised);
}
};
@ -162,48 +162,48 @@ namespace test{
{
// origin at lower end of the time range
FixedFrameQuantiser case1 (1, Time::MIN);
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) ));
CHECK (secs(0) == case1.gridLocal(Time::MIN ));
CHECK (secs(0) == case1.gridLocal(Time::MIN +TimeValue(1) ));
CHECK (secs(1) == case1.gridLocal(Time::MIN +secs(1) ));
CHECK (Time::MAX -secs(1) > case1.gridLocal( secs(-1) ));
CHECK (Time::MAX -secs(1) <= case1.gridLocal( secs (0) ));
CHECK (Time::MAX > case1.gridLocal( secs (0) ));
CHECK (Time::MAX == case1.gridLocal( secs(+1) ));
CHECK (Time::MAX == case1.gridLocal( secs(+2) ));
// origin at upper end of the time range
FixedFrameQuantiser case2 (1, Time::MAX);
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
CHECK (secs( 0) == case2.gridLocal(Time::MAX ));
CHECK (secs(-1) == case2.gridLocal(Time::MAX -TimeValue(1) )); // note: next lower frame
CHECK (secs(-1) == case2.gridLocal(Time::MAX -secs(1) )); // i.e. the same as a whole frame down
CHECK (Time::MIN +secs(1) < case2.gridLocal( secs(+2) ));
CHECK (Time::MIN +secs(1) >= case2.gridLocal( secs(+1) ));
CHECK (Time::MIN < case2.gridLocal( secs(+1) ));
CHECK (Time::MIN == case2.gridLocal( secs( 0) )); // note: because of downward truncating,
CHECK (Time::MIN == case2.gridLocal( secs(-1) )); // resulting values will already exceed
CHECK (Time::MIN == case2.gridLocal( secs(-2) )); // allowed range and thus will be clipped
// use very large frame with size of half the time range
Duration hugeFrame(Time::MAX);
FixedFrameQuantiser case3 (hugeFrame);
CHECK (Time::MIN == case3.gridAlign(Time::MIN ));
CHECK (Time::MIN == case3.gridAlign(Time::MIN +TimeValue(1) ));
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) ));
CHECK (Time::MAX == case3.gridAlign(Time::MAX ));
CHECK (Time::MIN == case3.gridLocal(Time::MIN ));
CHECK (Time::MIN == case3.gridLocal(Time::MIN +TimeValue(1) ));
CHECK (Time::MIN == case3.gridLocal( secs(-1) ));
CHECK (TimeValue(0) == case3.gridLocal( secs( 0) ));
CHECK (TimeValue(0) == case3.gridLocal( secs(+1) ));
CHECK (TimeValue(0) == case3.gridLocal(Time::MAX -TimeValue(1) ));
CHECK (Time::MAX == case3.gridLocal(Time::MAX ));
// now displacing this grid by +1sec....
FixedFrameQuantiser case4 (hugeFrame, secs(1));
CHECK (Time::MIN == case4.gridAlign(Time::MIN ));
CHECK (Time::MIN == case4.gridAlign(Time::MIN +TimeValue(1) )); // clipped...
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
CHECK (Time::MIN == case4.gridLocal(Time::MIN ));
CHECK (Time::MIN == case4.gridLocal(Time::MIN +TimeValue(1) )); // clipped...
CHECK (Time::MIN == case4.gridLocal(Time::MIN +secs(1) )); // but now exact (unclipped)
CHECK (Time::MIN == case4.gridLocal( secs(-1) ));
CHECK (Time::MIN == case4.gridLocal( secs( 0) ));
CHECK (TimeValue(0) == case4.gridLocal( secs(+1) )); //.....now exactly the frame number zero
CHECK (TimeValue(0) == case4.gridLocal(Time::MAX -TimeValue(1) ));
CHECK (TimeValue(0) == case4.gridLocal(Time::MAX )); //.......still truncated down to frame #0
// think big...
Duration superHuge{secs(12345) + hugeFrame};
@ -212,34 +212,34 @@ namespace test{
// Time::MAX < superHuge < Duration::Max is possible, but we can accommodate only one
FixedFrameQuantiser case5 (superHuge);
CHECK (TimeValue(0) == case5.gridAlign(Time::MAX ));
CHECK (TimeValue(0) == case5.gridAlign(Time::MAX -TimeValue(1) ));
CHECK (TimeValue(0) == case5.gridAlign( secs( 1) ));
CHECK (TimeValue(0) == case5.gridAlign( secs( 0) ));
CHECK (Time::MIN == case5.gridAlign( secs(-1) ));
CHECK (Time::MIN == case5.gridAlign(Time::MIN +TimeValue(1) ));
CHECK (Time::MIN == case5.gridAlign(Time::MIN ));
CHECK (TimeValue(0) == case5.gridLocal(Time::MAX ));
CHECK (TimeValue(0) == case5.gridLocal(Time::MAX -TimeValue(1) ));
CHECK (TimeValue(0) == case5.gridLocal( secs( 1) ));
CHECK (TimeValue(0) == case5.gridLocal( secs( 0) ));
CHECK (Time::MIN == case5.gridLocal( secs(-1) ));
CHECK (Time::MIN == case5.gridLocal(Time::MIN +TimeValue(1) ));
CHECK (Time::MIN == case5.gridLocal(Time::MIN ));
// now with offset
FixedFrameQuantiser case6 (superHuge, Time::MAX-secs(1));
CHECK (TimeValue(0) == case6.gridAlign(Time::MAX ));
CHECK (TimeValue(0) == case6.gridAlign(Time::MAX -TimeValue(1) ));
CHECK (TimeValue(0) == case6.gridAlign(Time::MAX -secs(1) ));
CHECK (Time::MIN == case6.gridAlign(Time::MAX -secs(2) ));
CHECK (Time::MIN == case6.gridAlign( secs( 1) ));
CHECK (Time::MIN == case6.gridAlign( secs(-12345) ));
CHECK (Time::MIN == case6.gridAlign( secs(-12345-1) ));
CHECK (Time::MIN == case6.gridAlign( secs(-12345-2) )); // this would be one frame lower, but is clipped
CHECK (Time::MIN == case6.gridAlign(Time::MIN +TimeValue(1) ));
CHECK (Time::MIN == case6.gridAlign(Time::MIN )); // same... unable to represent time points before Time::MIN
CHECK (TimeValue(0) == case6.gridLocal(Time::MAX ));
CHECK (TimeValue(0) == case6.gridLocal(Time::MAX -TimeValue(1) ));
CHECK (TimeValue(0) == case6.gridLocal(Time::MAX -secs(1) ));
CHECK (Time::MIN == case6.gridLocal(Time::MAX -secs(2) ));
CHECK (Time::MIN == case6.gridLocal( secs( 1) ));
CHECK (Time::MIN == case6.gridLocal( secs(-12345) ));
CHECK (Time::MIN == case6.gridLocal( secs(-12345-1) ));
CHECK (Time::MIN == case6.gridLocal( secs(-12345-2) )); // this would be one frame lower, but is clipped
CHECK (Time::MIN == case6.gridLocal(Time::MIN +TimeValue(1) ));
CHECK (Time::MIN == case6.gridLocal(Time::MIN )); // same... unable to represent time points before Time::MIN
// maximum frame size is spanning the full time range
FixedFrameQuantiser case7 (extraHuge, Time::MIN+secs(1));
CHECK (TimeValue(0) == case7.gridAlign(Time::MAX )); // rounded down one frame, i.e. to origin
CHECK (TimeValue(0) == case7.gridAlign( secs( 0) ));
CHECK (TimeValue(0) == case7.gridAlign(Time::MIN+secs(2) ));
CHECK (TimeValue(0) == case7.gridAlign(Time::MIN+secs(1) )); // exactly at origin
CHECK (Time::MIN == case7.gridAlign(Time::MIN )); // one frame further down, but clipped to Time::MIN
CHECK (TimeValue(0) == case7.gridLocal(Time::MAX )); // rounded down one frame, i.e. to origin
CHECK (TimeValue(0) == case7.gridLocal( secs( 0) ));
CHECK (TimeValue(0) == case7.gridLocal(Time::MIN+secs(2) ));
CHECK (TimeValue(0) == case7.gridLocal(Time::MIN+secs(1) )); // exactly at origin
CHECK (Time::MIN == case7.gridLocal(Time::MIN )); // one frame further down, but clipped to Time::MIN
// even larger frames aren't possible
Duration not_really_larger(secs(10000) + extraHuge);

View file

@ -109,7 +109,7 @@ namespace test {
ASSERT (0 < dirt);
Time dirty(point + Time(dirt));
CHECK (point == TEST_ORIGIN + myGrid->gridAlign(dirty));
CHECK (point == TEST_ORIGIN + myGrid->gridLocal(dirty));
}

View file

@ -41108,7 +41108,7 @@
<icon BUILTIN="button_ok"/>
</node>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1670191753771" ID="ID_838942043" MODIFIED="1670191797559" TEXT="Nebenbei bemerkt: das Grid::gridAligned() - API ist &#x201e;&#xfc;berraschend&#x201c;">
<node COLOR="#435e98" CREATED="1670191753771" ID="ID_838942043" MODIFIED="1670197700477" TEXT="Nebenbei bemerkt: das Grid::gridAligned() - API ist &#x201e;&#xfc;berraschend&#x201c;">
<icon BUILTIN="messagebox_warning"/>
<node CREATED="1670191803951" ID="ID_62422663" MODIFIED="1670191874006" TEXT="das Ergebnis ist relativ zum Grid-Origin">
<icon BUILTIN="info"/>
@ -41150,19 +41150,46 @@
<icon BUILTIN="forward"/>
</node>
</node>
<node BACKGROUND_COLOR="#fdfdcf" COLOR="#ff0000" CREATED="1670192170956" ID="ID_1026606570" MODIFIED="1670192201815" TEXT="API &#xe4;ndern: gridAligned() soll den Origin mit einschlie&#xdf;en">
<node COLOR="#690f14" CREATED="1670192170956" ID="ID_1026606570" MODIFIED="1670201051650" TEXT="API &#xe4;ndern: gridAlign() soll den Origin mit einschlie&#xdf;en">
<icon BUILTIN="yes"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1670192209793" ID="ID_1904533160" MODIFIED="1670192229367" TEXT="Limitierung bedenken">
<icon BUILTIN="flag-yellow"/>
<icon BUILTIN="stop-sign"/>
<node CREATED="1670200909516" ID="ID_1643706345" MODIFIED="1670200945558" TEXT="besser doch nicht: die Funtion w&#xe4;re dann n&#xe4;mlich komplett redundant"/>
<node CREATED="1670200914583" ID="ID_316481460" MODIFIED="1670201239789" TEXT="die gew&#xfc;nschte Funktion gibt es bereits auf dem Quantiser-API">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<p>
<font face="Monospaced" size="2">TimeValue Quantiser::materialise(TimeValue const&amp; raw) { return timeOf (gridPoint (raw)); }</font>
</p>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1670192204551" ID="ID_1757335290" MODIFIED="1670192230352" TEXT="Implementierung anpassen">
<icon BUILTIN="flag-yellow"/>
<node CREATED="1670201304802" ID="ID_1724553119" MODIFIED="1670201393006" TEXT="und letztere hat zudem den Vorteil, da&#xdf; sie nicht clippt">
<richcontent TYPE="NOTE"><html>
<head>
</head>
<body>
<ul>
<li>
weil die Rechnung komplett auf Implementierungs-Ebene passiert, mit int64_t
</li>
<li>
unter der Ma&#223;gabe da&#223; die auftretenden Werte dahingehend limititert sind, und daher auch noch die Summe zum Origin ohne wrap-around berechnet werden kann
</li>
</ul>
</body>
</html></richcontent>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1670192239363" ID="ID_968994817" MODIFIED="1670192243152" TEXT="dokumentieren">
<icon BUILTIN="flag-yellow"/>
</node>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1670192231262" ID="ID_185488622" MODIFIED="1670192236941" TEXT="Test anpassen">
<icon BUILTIN="flag-yellow"/>
<node COLOR="#338800" CREATED="1670200952970" ID="ID_2558241" MODIFIED="1670197706677" TEXT="API-Funtkion umbenennen">
<icon BUILTIN="button_ok"/>
<node CREATED="1670200964176" ID="ID_795458621" MODIFIED="1670201044967" TEXT="gridAlign() &#x27fc; gridLocal()"/>
<node CREATED="1670201059514" ID="ID_489288280" MODIFIED="1670201082523" TEXT="das macht dann wenigstens den Unterschied klar">
<node CREATED="1670201083498" ID="ID_1913733433" MODIFIED="1670201094684" TEXT="Input: eine globale freie Zeit"/>
<node CREATED="1670201095403" ID="ID_1247848116" MODIFIED="1670201105896" TEXT="Output: eine grit-relative, quantisierte Zeit"/>
</node>
</node>
</node>
@ -58042,6 +58069,7 @@
</node>
<node BACKGROUND_COLOR="#d2beaf" COLOR="#5c4d6e" CREATED="1667476797049" FOLDED="true" ID="ID_767502481" MODIFIED="1667770624162" TEXT="Diskussion: interne Zeitbasis">
<linktarget COLOR="#af1a4c" DESTINATION="ID_767502481" ENDARROW="Default" ENDINCLINATION="96;-430;" ID="Arrow_ID_1672039685" SOURCE="ID_1838246834" STARTARROW="None" STARTINCLINATION="-670;38;"/>
<linktarget COLOR="#535cb5" DESTINATION="ID_767502481" ENDARROW="Default" ENDINCLINATION="-9;23;" ID="Arrow_ID_1371034703" SOURCE="ID_368365221" STARTARROW="None" STARTINCLINATION="-97;6;"/>
<icon BUILTIN="hourglass"/>
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1667486621881" ID="ID_566152244" MODIFIED="1667486629636" TEXT="#1258 clarify internal time base">
<icon BUILTIN="flag-yellow"/>