{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Generic.Piece (
T, run,
step, linear, exponential,
cosine, halfSine, cubic,
FlatPosition(..),
) where
import qualified Synthesizer.Piecewise as Piecewise
import Synthesizer.Piecewise (FlatPosition (FlatLeft, FlatRight))
import qualified Synthesizer.Generic.Control as Ctrl
import qualified Synthesizer.Generic.Cut as CutG
import qualified Synthesizer.Generic.Signal as SigG
import Synthesizer.Generic.Displacement (raise, )
import qualified Algebra.Transcendental as Trans
import qualified Algebra.RealField as RealField
import qualified Algebra.Field as Field
import NumericPrelude.Numeric
import NumericPrelude.Base
{-# INLINE run #-}
run :: (RealField.C a, CutG.Transform (sig a)) =>
SigG.LazySize ->
Piecewise.T a a (SigG.LazySize -> a -> sig a) ->
sig a
run lazySize xs =
SigG.concat $ zipWith
(\(n, t) (Piecewise.PieceData c yi0 yi1 d) ->
SigG.take n $ Piecewise.computePiece c yi0 yi1 d lazySize t)
(Piecewise.splitDurations $ map Piecewise.pieceDur xs)
xs
type T sig a =
Piecewise.Piece a a
(SigG.LazySize -> a -> sig a)
{-# INLINE step #-}
step :: (SigG.Write sig a) => T sig a
step =
Piecewise.pieceFromFunction $ \ y0 _y1 _d lazySize _t0 ->
Ctrl.constant lazySize y0
{-# INLINE linear #-}
linear :: (Field.C a, SigG.Write sig a) => T sig a
linear =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
let s = (y1-y0)/d
in Ctrl.linear lazySize s (y0-t0*s)
{-# INLINE exponential #-}
exponential :: (Trans.C a, SigG.Write sig a) => a -> T sig a
exponential saturation =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
let y0' = y0-saturation
y1' = y1-saturation
yd = y0'/y1'
in raise saturation
(Ctrl.exponential lazySize (d / log yd) (y0' * yd**(t0/d)))
{-# INLINE cosine #-}
cosine :: (Trans.C a, SigG.Write sig a) => T sig a
cosine =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
SigG.map
(\y -> ((1+y)*y0+(1-y)*y1)/2)
(Ctrl.cosine lazySize t0 (t0+d))
{-# INLINE halfSine #-}
halfSine :: (Trans.C a, SigG.Write sig a) => FlatPosition -> T sig a
halfSine FlatLeft =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
SigG.map
(\y -> y*y0 + (1-y)*y1)
(Ctrl.cosine lazySize t0 (t0+2*d))
halfSine FlatRight =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
SigG.map
(\y -> (1+y)*y0 - y*y1)
(Ctrl.cosine lazySize (t0-d) (t0+d))
{-# INLINE cubic #-}
cubic :: (Field.C a, SigG.Write sig a) => a -> a -> T sig a
cubic yd0 yd1 =
Piecewise.pieceFromFunction $ \ y0 y1 d lazySize t0 ->
Ctrl.cubicHermite lazySize (t0,(y0,yd0)) (t0+d,(y1,yd1))