| Safe Haskell | Safe-Inferred |
|---|
Derive.Warp
Contents
Description
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.
Constructors
| Linear | |
Fields | |
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 #