Safe Haskell | Safe-Inferred |
---|
Functions for the Warp
.
Synopsis
- data Warp
- data Linear = Linear {}
- is_linear :: Warp -> Maybe Linear
- is_identity :: Warp -> Bool
- warp :: Warp -> ScoreTime.ScoreTime -> RealTime.RealTime
- unwarp :: Warp -> RealTime.RealTime -> ScoreTime.ScoreTime
- identity :: Warp
- from_signal :: Signal.Warp -> Warp
- compose :: Warp -> Warp -> Warp
- shift :: ScoreTime.ScoreTime -> Warp -> Warp
- stretch :: ScoreTime.ScoreTime -> Warp -> Warp
- unwarp_signal :: Warp -> Signal.Control -> Signal.Display
- compose_hybrid :: Warp -> Warp -> Warp
Documentation
The Warp
keeps track of the ScoreTime -> RealTime function, as well
as its inverse.
This treats linear warps specially, since they're common and allow some optimizations.
The main transformation is compose
, but shift
and stretch
are
shortcuts for composing with f(x) = y + shift
or f(x) = y * stretch
,
respectively.
The confusing thing is that shift and stretch compose with the *input* of
the function, so shift n
is (
. This means
that compose
shift n identity)shift 1 . stretch 2
is actually (*2) . (+1)
, which makes
compositions look backwards. It turns out this is more convenient since
Deriver level shift and stretch go in left-to-right order since monadic
effects go left to right:
Reader.runReader (Reader.local (+1) . Reader.local (*2) $ Reader.ask) 0
is 2, not 1.
There is probably some kind of theory to do with positive position or negative position or some such thing, but my tiny brain can't quite get a handle on it, so all I can say is that this is the way that makes things work out right.
is_identity :: Warp -> Bool Source #
warp :: Warp -> ScoreTime.ScoreTime -> RealTime.RealTime Source #
unwarp :: Warp -> RealTime.RealTime -> ScoreTime.ScoreTime Source #
1:1 identity warp. Previously I could detect this to optimize it away,
but since compose
is cheap now, I might not need that anymore.
from_signal :: Signal.Warp -> Warp Source #
Create a Warp from a signal and its inverse. This assumes the signal is monotonically increasing.
Times <0 always pass through unchanged. This is because warps start at 0, since tracks start at 0, but events may be moved before it. Since there's no tempo data there, I need to make something up, and I might as well make up id. TODO error on empty signal? or id?
stretch :: ScoreTime.ScoreTime -> Warp -> Warp Source #
See Warp
.
Previously, this would disallow <=0 stretch, but it turns out to be useful to stretch events to 0, and to negative durations.
utils
unwarp_signal :: Warp -> Signal.Control -> Signal.Display Source #