These pages from the TiddlyWiky feature a complete glossary of terms relevant for time and timecode handling, plus the architecural decisions related to this topic
186 lines
10 KiB
Text
186 lines
10 KiB
Text
Time Usage Situations
|
|
=====================
|
|
:Author: Hermann Voßeler
|
|
:Email: <Ichthyostega@web.de>
|
|
:Date: Spring 2011
|
|
|
|
//Menu: label Time Usage
|
|
|
|
the following collection of usage situations helps to shape the details of the
|
|
time values and time quantisation design. +
|
|
-> see also link:TimeQuant.html[more about time quantisation]
|
|
|
|
time position of an object::
|
|
indeed the term ``time position'' encompasses two quite different questions
|
|
+
|
|
* a time or timing specification within the object
|
|
* determining the time point in reference to an existing scale
|
|
|
|
time and length of an object::
|
|
basically the same situation, +
|
|
but the length of a time span (duration) could be treated in two ways for quantisation
|
|
+
|
|
* having a precise specification and then quantise the start and endpoint
|
|
* quantise the start position and then establish an (independently quantised length)
|
|
|
|
moving and resizing an object::
|
|
this can in itself be done in two different ways, and each of them can be
|
|
applied in a quantised flavour, which sums up to 8 possible combinations,
|
|
considering that position and length are 2 degrees of freedom.
|
|
+
|
|
* a variable can be _changed_ by an offset
|
|
* a variable can be _defined_ to a new value
|
|
* another (hidden) degree of freedom lies in how to apply an quantised offset
|
|
to an unquantised value (and reversed), because this operation might be done
|
|
both in the quantised or non-quantised domain, and also the result might be
|
|
(un)quantised
|
|
|
|
updating the playback position::
|
|
this can be seen as a practical application of the above; basically we can
|
|
choose to show the wall clock time or we can advance the playback position in
|
|
frame increments, thus denoting the frame currently in display. For video,
|
|
these distinctions may look moot, but they are indeed relevant for precise
|
|
audio editing, especially when combined with loop playback (recall that audio
|
|
is processed block wise, but the individual sample frames and thus the
|
|
possible loop positions are way finer than the processing block size)
|
|
|
|
dispatching individual frames for calculation::
|
|
when a link:PlayProcess[render or playback process] is created, at some point
|
|
we need to translate this logical unit (``calculation stream'') into individual
|
|
frame job entries. This requires to break continuous time into individual
|
|
frames, and then ennumerating these frames.
|
|
|
|
displaying time intervals::
|
|
for display, time intervals get _re-quantised_ into display array
|
|
coordinates. While evidently the display coordinates are themselves quantised
|
|
and we obviously don't want to cancel out the effect of an quantisation of the
|
|
values or intervals to be displayed (which means, we get two quantisations
|
|
chained up after each other), there remains the question if the display array
|
|
coordinates should be aligned to the grid of the _elements to be displayed,_
|
|
and especially if the allowed zoom factors should be limited. This decision
|
|
isn't an easy one, as it has an immediate and tangible effect on what can be
|
|
showed, how reversible and reproducible a view is and (especially note this!)
|
|
on the actual values which can be set and changed through the GUI.
|
|
|
|
time value arithmetic::
|
|
Client code as well as the internal implementation of time handling needs to
|
|
do arithmetic operations with time values. Time values are additive and
|
|
totally ordered. Distance, as calculated by subtraction, can be made into a
|
|
metric. Another and quite different question is to what extent a quantised
|
|
variant of this arithmetics is required.
|
|
|
|
relative placement::
|
|
because of the divergence between quantised and unquantised values the
|
|
question arises, if placement relative to another object refers to the raw
|
|
position or the already quantised position. Basically all the variations
|
|
discussed for _time and length of an object_ also do apply here.
|
|
|
|
|
|
notable issues
|
|
--------------
|
|
|
|
*Direct quantisation of length is not possible*. This is due to the non-linear
|
|
nature of all but the most trivial time grids: Already such a simple addition
|
|
like a start offset destroys linearity, and this still the more is true within a
|
|
compound grid where the grid spacing changes at some point. Thus, the length has
|
|
to be re-established at the target position of an time interval after each
|
|
change involving quantisation. Regarding the _strategy_ to apply when
|
|
re-establishing the length, it seems more appropriate to treat the object as an
|
|
entity which is moved, which means to do quantisation in two steps, first the
|
|
position, then the endpoint (the second option in the description above). But it
|
|
seems advisable not to hard wire that strategy -- better put it into the
|
|
quantiser.
|
|
|
|
We should note that the problems regarding quantised durations also carry over
|
|
to _offsets:_ it is difficult to *define the semantics of a quantised offset*.
|
|
Seemingly the only viable approach is to have a _intended offset,_ and then
|
|
to apply a re-quantisation to the target after applying the (raw) offset.
|
|
|
|
*When to materialise a quantisation*. Because of the basic intention to retain
|
|
information, we prefer to delay the actual applicatio of the quantisation operation
|
|
to the values stored internally as much as possible. But not materialising
|
|
immediately at quantisation has the downside of possibly accumulating off-grid
|
|
values without that being evident. Most notably, if we apply the raw offsets
|
|
produced by GUI interactions, the object's positions and lengthes are bound to
|
|
accumulate spurious information never intended by the user.
|
|
|
|
Thus, an especially important instance of that problem is *how to deal with
|
|
updates in a quantised environment*. If we handle quantisation stictly as a
|
|
view employed on output, we run into the problems with accumulating spurious
|
|
information. On the other hand, allowing for quantised changes inevitably pulls
|
|
in all the complexity of mixing quantised and non-quantised values. It would be
|
|
desirable somehow to move these distinctions out of the scope of this design and
|
|
offload them onto the client (code using these time classes).
|
|
|
|
Another closely related problem is *when to allow mutations*, if at all (-> see
|
|
link:TimeMutation[more here...]). We can't completely do away with mutations,
|
|
simply because we don't have a pure functional language at our disposal. The
|
|
whole concept of _reference semantics_ doesn't play so well with immutable
|
|
objects. The Lumiera high-level (session) model certainly relies on objects
|
|
intended to be _manipulated._ Thus we need a re-settable length field in
|
|
`MObject` and we need a time variable for position calculations. Yet we
|
|
could make any _derived objects_ into immutable descriptor records, which
|
|
certainly helps with parallelism.
|
|
|
|
The *problem with playback position* is -- that indeed it's an attempt to
|
|
conceptualise a non-existing entity. There is no such thing like ``the'' playback
|
|
position. Yet most applications I'm aware off _do_ employ this concept. Likely
|
|
they got trapped by the metaphor of the tape head, again. We should do away with
|
|
that. On playback, we should show a _projection of wall-clock time onto the
|
|
expected playback range_ -- not more, not less. It should be acknowledged that
|
|
there is _no direct link to the ongoing playback processes,_ besides the fact
|
|
that they're assumed to sync to wall-clock time as well. Recall, typically there
|
|
are multiple playback processes going on in compound, and each might run on a
|
|
different update rate. If we really want a _visual out-of-sync indicator,_ we
|
|
should treat that as a separate reporting facility and display it apart of the
|
|
playback cursor.
|
|
|
|
An interesting point to note for the *frame dispatch step* is the fact that
|
|
in this case quantised values and quantisation are approached in the reverse
|
|
direction, compared with the other uses. Here, after establishing a start point
|
|
on the time scale, we proceed with ennumerating distinct frames and later on
|
|
need to access the corresponding raw time, especially to find out about the
|
|
link:Segmentation[timeline segment] to address, or for retrieving parameter
|
|
automation. -> link:FrameDispatcher[see frame dispatching].
|
|
|
|
Note that the *display window might be treated as just an independent instance
|
|
of quantisation*. This is similar to the approach taken above for modifying
|
|
quantised time span values. When following this line of thought, we should
|
|
provide a special kind of time grid, the display coordinates. The origin of
|
|
these is always defined to the left (lower) side of the interval to be
|
|
displayed, and they are gauged in screen units (pixels or similar, as used by
|
|
the GUI toolkit set). The rest is handled by the general quantisation
|
|
mechanisms. The problem of aligning the display should be transformed into a
|
|
general facility to align grids, and solved for the general case. Doing so
|
|
solves the remaining problems with quantised value changes and with *specifying
|
|
relative placements* as well: If we choose to represent them as quantised
|
|
values, we might (or might not) also choose to apply this _grid-alignment function._
|
|
|
|
|
|
the complete time value usage cycle
|
|
-----------------------------------
|
|
|
|
The way time value and quantisation handling is designed in Lumiera creates a
|
|
typical usage path, which actually is a one-way route. We might start out with a
|
|
textual representation according to a specific *timecode* format. Assumed we
|
|
know the implicit underlying *time grid* (coordinate system, framerate), this
|
|
timecode string may be parsed. This brings us (back) to the very origin, which
|
|
is a raw `TimeValue` (*internal time* value). Now, this time value might be
|
|
manipulated, compared to other values, combined into a *time span* (time point
|
|
and duration -- the most basic notion of an _object_ to be manipulated in the
|
|
Session). Anyway, at some point these time values need to be related to some
|
|
*time scale* again, leading to *quantised* time values, which -- finally --
|
|
can be cast into a timecode format for external representation again, thus
|
|
closing the circle.
|
|
|
|
|
|
substantial problems to be solved
|
|
---------------------------------
|
|
* how to link:TimeGridAlignment[align multiple grids]
|
|
* how to integrate link:TimeMutation[modifications of quantised values]. ([green]#✔ solved#)
|
|
* how to isolate the Time/Quantisation part from the grid MetaAsset in the
|
|
session -> we use the link:Advice[Advice] system ([green]#✔ solved#)
|
|
* how to design the relation of Timecode, Timecode formatting and Quantisation
|
|
-> link:TimecodeFormat[more here] [yellow-background]#WIP#
|
|
|
|
|