Lumiera 0.pre.04
»edit your freedom«
Loading...
Searching...
No Matches
quantiser.cpp
Go to the documentation of this file.
1/*
2 Quantiser - aligning time values to a time grid
3
4 Copyright (C)
5 2010, Stefan Kangas <skangas@skangas.se>
6 2010-2025, Hermann Vosseler <Ichthyostega@web.de>
7
8  **Lumiera** is free software; you can redistribute it and/or modify it
9  under the terms of the GNU General Public License as published by the
10  Free Software Foundation; either version 2 of the License, or (at your
11  option) any later version. See the file COPYING for further details.
12
13* *****************************************************************/
14
15
24#include "lib/util-quant.hpp"
25#include "lib/rational.hpp"
26
27using std::string;
28
29
30namespace error = lumiera::error;
31
32namespace lib {
33namespace time {
34
35 namespace { // implementation: basic frame quantisation....
36
42 inline int64_t
43 calculate_quantisation (raw_time_64 time, uint64_t framerate, uint64_t framerate_divisor=1)
44 {
45 REQUIRE (framerate);
46 REQUIRE (framerate_divisor);
47
48 const uint64_t MAXRANGE = std::numeric_limits<raw_time_64>::max();
49 const int64_t limit_num = MAXRANGE / framerate;
50 const int64_t limit_den = MAXRANGE / framerate_divisor;
51 const int64_t microScale {lib::time::TimeValue::SCALE};
52
53 // protect against numeric overflow
54 if (abs(time) < limit_num and microScale < limit_den)
55 {
56 // safe to calculate "time * framerate"
57 return util::floordiv (time*int64_t(framerate), microScale*int64_t(framerate_divisor));
58 }
59 else
60 {
61 // direct calculation will overflow;
62 // thus approximate the grid spacing by re-quantisation into µ-tick scale
63 // (since in the end we will alias to the microScale anyway)...
64 const uint64_t LIM{MAXRANGE/microScale};
65 if (framerate > LIM or framerate_divisor > LIM)
66 {
67 framerate = util::reQuant (framerate,framerate_divisor, LIM);
68 framerate_divisor = LIM;
69 }
70 // Note : frameDuration ≡ microScale / (framerate/framerate_divisor)
71 raw_time_64 frameDuration = util::reQuant (framerate_divisor,framerate, microScale);
72 return util::floordiv (time,frameDuration);
73 }
74 }
75 }
76
85 int64_t
87 {
88 return util::floordiv (_raw(time), _raw(grid));
89 }
90
91
92
93 PQuant
95 {
96 static PQuant globalDefaultGrid (new FixedFrameQuantiser(1));
97 return globalDefaultGrid;
98 };
99
100
101
102
103
104 Grid::~Grid() { } // hint to emit the VTable here...
105
106
107 /* Note: the ctor QuTime(TimeValue, Symbol) and the static function
108 * PQuant Quantiser::retrieve (Symbol) are defined in common-services.cpp
109 * To use this special convenience shortcuts, you need to link against liblumieracore.so
110 * This allows to use the Advice-system to retrieve grid definitions directly from the session
111 */
112
113
120 QuTime::QuTime (TimeValue raw, PQuant quantisation_to_use)
121 : Time(raw)
122 , quantiser_(quantisation_to_use)
123 { }
124
125
126
131 FixedFrameQuantiser::FixedFrameQuantiser (FrameRate const& frames_per_second, TimeValue referencePoint)
132 : origin_(referencePoint)
133 , raster_(__ensure_nonzero(frames_per_second.duration()))
134 { }
135
136 FixedFrameQuantiser::FixedFrameQuantiser (Duration const& frame_duration, TimeValue referencePoint)
137 : origin_(referencePoint)
138 , raster_(__ensure_nonzero(frame_duration))
139 { }
140
141
142
143
158 {
159 return timeOf (gridPoint (raw));
160 }
161
162
163
174 {
175 return grid_aligned (Offset{origin_, rawTime}, raster_);
176 }
177
178
191 Offset
193 {
194 return raster_ * grid_aligned (Offset{origin_, rawTime}
195 ,raster_);
196 }
197
198
207 {
208 return origin_ + gridPoint * raster_;
209 }
210
211
220 FixedFrameQuantiser::timeOf (FSecs gridTime, int gridOffset) const
221 {
222 Time gt(gridTime);
223 TimeVar timePoint = gt + origin_;
224 timePoint += gridOffset * Offset(raster_);
225 return timePoint;
226 }
227
228
229
230
231 LUMIERA_ERROR_DEFINE (UNKNOWN_GRID, "referring to an undefined grid or scale in value quantisation");
232
233
234
235
236
237
238 /* ===== NTSC drop-frame conversions ===== */
239
240 namespace { // conversion parameters
241
242 const uint FRAMES_PER_10min = 10*60 * 30000/1001;
243 const uint FRAMES_PER_1min = 1*60 * 30000/1001;
244 const uint DISCREPANCY = (1*60 * 30) - FRAMES_PER_1min;
245 }
246
247
256 int64_t
258 {
259 int64_t frameNr = calculate_quantisation (time, 30000, 1001);
260
261 // partition into 10 minute segments
262 lldiv_t tenMinFrames = lldiv (frameNr, FRAMES_PER_10min);
263
264 // ensure the drop-frame incidents happen at full minutes;
265 // at start of each 10-minute segment *no* drop incident happens,
266 // thus we need to correct discrepancy between nominal/real framerate once:
267 int64_t remainingMinutes = (tenMinFrames.rem - DISCREPANCY) / FRAMES_PER_1min;
268
269 int64_t dropIncidents = (10-1) * tenMinFrames.quot + remainingMinutes;
270 return frameNr + 2*dropIncidents;
271 }
272
273
283 {
284 int64_t total_mins = 60 * hours + mins;
285 int64_t total_frames = 30*60*60 * hours
286 + 30*60 * mins
287 + 30 * secs
288 + frames
289 - 2 * (total_mins - total_mins / 10);
290 raw_time_64 result = _raw (Offset{total_frames, FrameRate::NTSC});
291
292 if (0 != result) // compensate for truncating down on conversion
293 result += 1; // without this adjustment the frame number
294 return result; // would turn out off by -1 on back conversion
295 }
296
297}} // lib::time
Duration is the internal Lumiera time metric.
Simple stand-alone Quantiser implementation based on a constant sized gird.
FrameCnt gridPoint(TimeValue const &) const override
grid quantisation (alignment).
Offset gridLocal(TimeValue const &) const override
transform into the local time scale grid aligned.
FixedFrameQuantiser(FrameRate const &frames_per_second, TimeValue referencePoint=TimeValue(0))
Create a quantiser based on a fixed constant spaced grid, rooted at the reference point as origin of ...
TimeValue timeOf(FrameCnt gridPoint) const override
calculate time value of a grid interval (frame) start point
static int64_t grid_aligned(TimeValue const &, TimeValue const &)
Quantise the given time into a fixed grid, relative to the origin.
Definition quantiser.cpp:86
Framerate specified as frames per second.
static const FrameRate NTSC
virtual ~Grid()
this is an Interface
Offset measures a distance in time.
QuTime(TimeValue raw, Symbol gridID)
build a quantised time value, referring the time grid by-name.
TimeValue materialise(TimeValue const &raw) const
convenience shortcut: materialise a raw time value based on this grid or time axis,...
virtual TimeValue timeOf(FrameCnt gridPoint) const =0
virtual FrameCnt gridPoint(TimeValue const &raw) const =0
basic constant internal time value.
static const raw_time_64 SCALE
Number of micro ticks (µs) per second as basic time scale.
a mutable time value, behaving like a plain number, allowing copy and re-accessing
Lumiera's internal time value datatype.
#define LUMIERA_ERROR_DEFINE(err, msg)
Definition and initialisation of an error constant.
Definition error.h:71
unsigned int uint
Definition integral.hpp:29
int64_t raw_time_64
Definition job.h:50
int64_t calculate_quantisation(raw_time_64 time, uint64_t framerate, uint64_t framerate_divisor=1)
Grid-align the raw time to a frame grid, which can be fractional.
Definition quantiser.cpp:43
int64_t FrameCnt
relative framecount or frame number.
Definition digxel.hpp:310
raw_time_64 build_time_from_ntsc_drop_frame(uint frames, uint secs, uint mins, uint hours)
Build effective time from a NTSC drop frame timecode.
PQuant getDefaultGridFallback()
Definition quantiser.cpp:94
std::shared_ptr< const Quantiser > PQuant
Definition formats.hpp:58
int64_t raw_time_64
Raw µ-tick time representation used in Lumiera.
int64_t calculate_ntsc_drop_frame_number(raw_time_64 time)
Compute the consecutive frame number from a given time, which is interpreted at the NTSC drop frame t...
boost::rational< int64_t > FSecs
rational representation of fractional seconds
Implementation namespace for support and library code.
I floordiv(I num, I den)
floor function for integer arithmetics.
int64_t reQuant(int64_t num, int64_t den, int64_t u)
Re-Quantise a number into a new grid, truncating to the next lower grid point.
Definition rational.hpp:120
Library functions to support the formation of grid-aligned time values.
Rational number support, based on boost::rational.
Support library to represent grid-aligned time specifications This is part of Lumiera's time and time...
a family of time value like entities and their relationships.
Utilities for quantisation (grid alignment) and comparisons.