module Derive.Warp (
Warp, Linear(..), is_linear, is_identity, warp, unwarp
, identity, from_signal, compose
, shift, stretch
, unwarp_signal
, compose_hybrid
) where
import qualified Control.DeepSeq as DeepSeq
import qualified Ui.ScoreTime as ScoreTime
import qualified Perform.RealTime as RealTime
import Perform.RealTime (to_score)
import qualified Perform.Signal as Signal
import Global
import Types
data Warp = WarpFunction !Function | WarpLinear !Linear
data Function = Function {
Function -> ScoreTime -> RealTime
_warp :: !(ScoreTime -> RealTime)
, Function -> RealTime -> ScoreTime
_unwarp :: !(RealTime -> ScoreTime)
}
data Linear = Linear { Linear -> RealTime
_shift :: !RealTime, Linear -> RealTime
_stretch :: !RealTime }
deriving (Int -> Linear -> ShowS
[Linear] -> ShowS
Linear -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Linear] -> ShowS
$cshowList :: [Linear] -> ShowS
show :: Linear -> String
$cshow :: Linear -> String
showsPrec :: Int -> Linear -> ShowS
$cshowsPrec :: Int -> Linear -> ShowS
Show)
instance Show Warp where show :: Warp -> String
show = forall a. Pretty a => a -> String
prettys
instance Pretty Warp where
pretty :: Warp -> Text
pretty (WarpFunction Function
f) = Text
"((Warp " forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty (Function -> ScoreTime -> RealTime
_warp Function
f ScoreTime
0) forall a. Semigroup a => a -> a -> a
<> Text
"--"
forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty (Function -> ScoreTime -> RealTime
_warp Function
f ScoreTime
1) forall a. Semigroup a => a -> a -> a
<> Text
"))"
pretty (WarpLinear (Linear RealTime
shift RealTime
stretch)) =
Text
"((Warp *" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty RealTime
stretch forall a. Semigroup a => a -> a -> a
<> Text
"+" forall a. Semigroup a => a -> a -> a
<> forall a. Pretty a => a -> Text
pretty RealTime
shift forall a. Semigroup a => a -> a -> a
<> Text
"))"
instance DeepSeq.NFData Warp where rnf :: Warp -> ()
rnf Warp
_ = ()
is_linear :: Warp -> Maybe Linear
is_linear :: Warp -> Maybe Linear
is_linear (WarpLinear Linear
linear) = forall a. a -> Maybe a
Just Linear
linear
is_linear Warp
_ = forall a. Maybe a
Nothing
is_identity :: Warp -> Bool
is_identity :: Warp -> Bool
is_identity (WarpLinear (Linear RealTime
shift RealTime
stretch)) = RealTime
shift forall a. Eq a => a -> a -> Bool
== RealTime
0 Bool -> Bool -> Bool
&& RealTime
stretch forall a. Eq a => a -> a -> Bool
== RealTime
1
is_identity Warp
_ = Bool
False
warp :: Warp -> ScoreTime -> RealTime
warp :: Warp -> ScoreTime -> RealTime
warp (WarpFunction Function
f) ScoreTime
t = Function -> ScoreTime -> RealTime
_warp Function
f ScoreTime
t
warp (WarpLinear Linear
w) ScoreTime
t = ScoreTime -> RealTime
to_real ScoreTime
t forall a. Num a => a -> a -> a
* Linear -> RealTime
_stretch Linear
w forall a. Num a => a -> a -> a
+ Linear -> RealTime
_shift Linear
w
unwarp :: Warp -> RealTime -> ScoreTime
unwarp :: Warp -> RealTime -> ScoreTime
unwarp (WarpFunction Function
f) = Function -> RealTime -> ScoreTime
_unwarp Function
f
unwarp (WarpLinear Linear
w) = RealTime -> ScoreTime
to_score forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Fractional a => a -> a -> a
/ Linear -> RealTime
_stretch Linear
w) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Num a => a -> a -> a
subtract (Linear -> RealTime
_shift Linear
w)
identity :: Warp
identity :: Warp
identity = Linear -> Warp
WarpLinear (RealTime -> RealTime -> Linear
Linear RealTime
0 RealTime
1)
signal_identity :: Warp
signal_identity :: Warp
signal_identity = Warp -> Warp
from_signal forall a b. (a -> b) -> a -> b
$ forall {k} (kind :: k). [(RealTime, Y)] -> Signal kind
Signal.from_pairs
[(RealTime
0, Y
0), (RealTime
RealTime.large, RealTime -> Y
RealTime.to_seconds RealTime
RealTime.large)]
from_signal :: Signal.Warp -> Warp
from_signal :: Warp -> Warp
from_signal Warp
signal = Function -> Warp
WarpFunction forall a b. (a -> b) -> a -> b
$ Function
{ _warp :: ScoreTime -> RealTime
_warp = ScoreTime -> RealTime
forward
, _unwarp :: RealTime -> ScoreTime
_unwarp = RealTime -> ScoreTime
backward
}
where
forward :: ScoreTime -> RealTime
forward ScoreTime
t
| ScoreTime
t forall a. Ord a => a -> a -> Bool
< ScoreTime
0 = ScoreTime -> RealTime
to_real ScoreTime
t
| Bool
otherwise = Y -> RealTime
RealTime.seconds forall a b. (a -> b) -> a -> b
$ forall {k} (kind :: k). Signal kind -> RealTime -> Y
Signal.at Warp
signal (ScoreTime -> RealTime
to_real ScoreTime
t)
backward :: RealTime -> ScoreTime
backward RealTime
t
| RealTime
t forall a. Ord a => a -> a -> Bool
< RealTime
0 = RealTime -> ScoreTime
to_score RealTime
t
| Bool
otherwise = Y -> ScoreTime
ScoreTime.from_double forall a b. (a -> b) -> a -> b
$ forall {k} (kind :: k). Signal kind -> RealTime -> Y
Signal.at Warp
inverted RealTime
t
where inverted :: Warp
inverted = forall {k} (kind :: k). Signal kind -> Signal kind
Signal.invert Warp
signal
compose :: Warp -> Warp -> Warp
compose :: Warp -> Warp -> Warp
compose (WarpLinear (Linear RealTime
shift1 RealTime
stretch1))
(WarpLinear (Linear RealTime
shift2 RealTime
stretch2)) =
Linear -> Warp
WarpLinear forall a b. (a -> b) -> a -> b
$ RealTime -> RealTime -> Linear
Linear (RealTime
shift1 forall a. Num a => a -> a -> a
+ RealTime
shift2 forall a. Num a => a -> a -> a
* RealTime
stretch1) (RealTime
stretch1 forall a. Num a => a -> a -> a
* RealTime
stretch2)
compose (WarpFunction (Function ScoreTime -> RealTime
warp1 RealTime -> ScoreTime
unwarp1))
(WarpFunction (Function ScoreTime -> RealTime
warp2 RealTime -> ScoreTime
unwarp2)) =
Function -> Warp
WarpFunction forall a b. (a -> b) -> a -> b
$ Function
{ _warp :: ScoreTime -> RealTime
_warp = ScoreTime -> RealTime
warp1 forall b c a. (b -> c) -> (a -> b) -> a -> c
. RealTime -> ScoreTime
to_score forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScoreTime -> RealTime
warp2
, _unwarp :: RealTime -> ScoreTime
_unwarp = RealTime -> ScoreTime
unwarp2 forall b c a. (b -> c) -> (a -> b) -> a -> c
. ScoreTime -> RealTime
to_real forall b c a. (b -> c) -> (a -> b) -> a -> c
. RealTime -> ScoreTime
unwarp1
}
compose (WarpLinear Linear
linear) (WarpFunction Function
f) =
Warp -> Warp -> Warp
compose (Linear -> Warp
to_function Linear
linear) (Function -> Warp
WarpFunction Function
f)
compose (WarpFunction Function
f) (WarpLinear Linear
linear) =
Warp -> Warp -> Warp
compose (Function -> Warp
WarpFunction Function
f) (Linear -> Warp
to_function Linear
linear)
to_function :: Linear -> Warp
to_function :: Linear -> Warp
to_function Linear
w = ScoreTime -> Warp -> Warp
stretch (RealTime -> ScoreTime
to_score (Linear -> RealTime
_stretch Linear
w)) forall a b. (a -> b) -> a -> b
$
ScoreTime -> Warp -> Warp
shift (RealTime -> ScoreTime
to_score (Linear -> RealTime
_shift Linear
w)) Warp
signal_identity
shift :: ScoreTime -> Warp -> Warp
shift :: ScoreTime -> Warp -> Warp
shift ScoreTime
0 Warp
w = Warp
w
shift ScoreTime
x (WarpFunction (Function ScoreTime -> RealTime
warp RealTime -> ScoreTime
unwarp)) = Function -> Warp
WarpFunction forall a b. (a -> b) -> a -> b
$ Function
{ _warp :: ScoreTime -> RealTime
_warp = ScoreTime -> RealTime
warp forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
+ScoreTime
x)
, _unwarp :: RealTime -> ScoreTime
_unwarp = forall a. Num a => a -> a -> a
subtract ScoreTime
x forall b c a. (b -> c) -> (a -> b) -> a -> c
. RealTime -> ScoreTime
unwarp
}
shift ScoreTime
x (WarpLinear Linear
linear) = Linear -> Warp
WarpLinear forall a b. (a -> b) -> a -> b
$ Linear
{ _shift :: RealTime
_shift = Linear -> RealTime
_shift Linear
linear forall a. Num a => a -> a -> a
+ Linear -> RealTime
_stretch Linear
linear forall a. Num a => a -> a -> a
* ScoreTime -> RealTime
to_real ScoreTime
x
, _stretch :: RealTime
_stretch = Linear -> RealTime
_stretch Linear
linear
}
stretch :: ScoreTime -> Warp -> Warp
stretch :: ScoreTime -> Warp -> Warp
stretch ScoreTime
1 Warp
w = Warp
w
stretch ScoreTime
factor (WarpFunction (Function ScoreTime -> RealTime
warp RealTime -> ScoreTime
unwarp)) = Function -> Warp
WarpFunction forall a b. (a -> b) -> a -> b
$ Function
{ _warp :: ScoreTime -> RealTime
_warp = ScoreTime -> RealTime
warp forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Num a => a -> a -> a
*ScoreTime
factor)
, _unwarp :: RealTime -> ScoreTime
_unwarp = (forall a. Fractional a => a -> a -> a
/ScoreTime
factor) forall b c a. (b -> c) -> (a -> b) -> a -> c
. RealTime -> ScoreTime
unwarp
}
stretch ScoreTime
factor (WarpLinear Linear
linear) = Linear -> Warp
WarpLinear forall a b. (a -> b) -> a -> b
$ Linear
{ _shift :: RealTime
_shift = Linear -> RealTime
_shift Linear
linear
, _stretch :: RealTime
_stretch = ScoreTime -> RealTime
to_real ScoreTime
factor forall a. Num a => a -> a -> a
* Linear -> RealTime
_stretch Linear
linear
}
unwarp_signal :: Warp -> Signal.Control -> Signal.Display
unwarp_signal :: Warp -> Control -> Display
unwarp_signal Warp
w = forall {k1} {k2} (kind1 :: k1) (kind2 :: k2).
Signal kind1 -> Signal kind2
Signal.coerce forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {k} (kind :: k).
(RealTime -> RealTime) -> Signal kind -> Signal kind
Signal.map_x (ScoreTime -> RealTime
to_real forall b c a. (b -> c) -> (a -> b) -> a -> c
. Warp -> RealTime -> ScoreTime
unwarp Warp
w)
to_real :: ScoreTime -> RealTime
to_real :: ScoreTime -> RealTime
to_real = ScoreTime -> RealTime
RealTime.from_score
compose_hybrid :: Warp -> Warp -> Warp
compose_hybrid :: Warp -> Warp -> Warp
compose_hybrid Warp
_ Warp
_ = Warp
identity