module Synthesizer.State.Control where
import qualified Synthesizer.Plain.Control as Ctrl
import qualified Synthesizer.Piecewise as Piecewise
import Synthesizer.State.Displacement (raise)
import qualified Synthesizer.State.Signal as Sig
import qualified Algebra.Module as Module
import qualified Algebra.Transcendental as Trans
import qualified Algebra.RealRing as RealRing
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import Algebra.Module((*>))
import Data.Ix (Ix, )
import qualified Prelude as P
import NumericPrelude.Base
import NumericPrelude.Numeric
constant :: a -> Sig.T a
constant = Sig.repeat
linear :: Additive.C a =>
a
-> a
-> Sig.T a
linear d y0 = Sig.iterate (d+) y0
linearMultiscale :: Additive.C y =>
y
-> y
-> Sig.T y
linearMultiscale = curveMultiscale (+)
linearMultiscaleNeutral :: Additive.C y =>
y
-> Sig.T y
linearMultiscaleNeutral slope =
curveMultiscaleNeutral (+) slope zero
line :: Field.C y =>
Int
-> (y,y)
-> Sig.T y
line n (y0,y1) =
Sig.take n $ linear ((y1y0) / fromIntegral n) y0
exponential, exponentialMultiscale :: Trans.C a =>
a
-> a
-> Sig.T a
exponential time =
Sig.iterate (exp ( recip time) *)
exponentialMultiscale time = curveMultiscale (*) (exp ( recip time))
exponentialMultiscaleNeutral :: Trans.C y =>
y
-> Sig.T y
exponentialMultiscaleNeutral time =
curveMultiscaleNeutral (*) (exp ( recip time)) one
exponential2, exponential2Multiscale :: Trans.C a =>
a
-> a
-> Sig.T a
exponential2 halfLife =
Sig.iterate (((Ring.one+Ring.one) ** ( recip halfLife)) *)
exponential2Multiscale halfLife = curveMultiscale (*) (0.5 ** recip halfLife)
exponential2MultiscaleNeutral :: Trans.C y =>
y
-> Sig.T y
exponential2MultiscaleNeutral halfLife =
curveMultiscaleNeutral (*) (0.5 ** recip halfLife) one
exponentialFromTo, exponentialFromToMultiscale :: Trans.C y =>
y
-> y
-> y
-> Sig.T y
exponentialFromTo time y0 y1 =
Sig.iterate (* (y1/y0) ** recip time) y0
exponentialFromToMultiscale time y0 y1 =
curveMultiscale (*) ((y1/y0) ** recip time) y0
vectorExponential :: (Trans.C a, Module.C a v) =>
a
-> v
-> Sig.T v
vectorExponential time y0 =
Sig.iterate (exp (1/time) *>) y0
vectorExponential2 :: (Trans.C a, Module.C a v) =>
a
-> v
-> Sig.T v
vectorExponential2 halfLife y0 =
Sig.iterate (0.5**(1/halfLife) *>) y0
cosine :: Trans.C a =>
a
-> a
-> Sig.T a
cosine = Ctrl.cosineWithSlope $
\d x -> Sig.map cos (linear d x)
cubicHermite :: Field.C a => (a, (a,a)) -> (a, (a,a)) -> Sig.T a
cubicHermite node0 node1 =
Sig.map (Ctrl.cubicFunc node0 node1) (linear 1 0)
splitDurations :: (RealRing.C t) =>
[t] -> [(Int, t)]
splitDurations ts0 =
let (ds,ts) =
unzip $ scanl
(\(_,fr) d -> splitFraction (fr+d))
(0,1) ts0
in zip (tail ds) (map (subtract 1) ts)
piecewise :: (RealRing.C a) =>
Piecewise.T a a (a -> Sig.T a) -> Sig.T a
piecewise xs =
Sig.concat $ zipWith
(\(n, t) (Piecewise.PieceData c yi0 yi1 d) ->
Sig.take n $ Piecewise.computePiece c yi0 yi1 d t)
(splitDurations $ map Piecewise.pieceDur xs)
xs
type Piece a =
Piecewise.Piece a a
(a -> Sig.T a)
stepPiece :: Piece a
stepPiece =
Piecewise.pieceFromFunction $ \ y0 _y1 _d _t0 ->
constant y0
linearPiece :: (Field.C a) => Piece a
linearPiece =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
let s = (y1y0)/d in linear s (y0t0*s)
exponentialPiece :: (Trans.C a) => a -> Piece a
exponentialPiece saturation =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
let y0' = y0saturation
y1' = y1saturation
yd = y0'/y1'
in raise saturation
(exponential (d / log yd) (y0' * yd**(t0/d)))
cosinePiece :: (Trans.C a) => Piece a
cosinePiece =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
Sig.map
(\y -> ((1+y)*y0+(1y)*y1)/2)
(cosine t0 (t0+d))
data FlatPosition =
FlatLeft | FlatRight
deriving (Show, Eq, Ord, Ix, Enum)
halfSinePiece :: (Trans.C a) => FlatPosition -> Piece a
halfSinePiece FlatLeft =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
Sig.map
(\y -> y*y0 + (1y)*y1)
(cosine t0 (t0+2*d))
halfSinePiece FlatRight =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
Sig.map
(\y -> (1+y)*y0 y*y1)
(cosine (t0d) (t0+d))
cubicPiece :: (Field.C a) => a -> a -> Piece a
cubicPiece yd0 yd1 =
Piecewise.pieceFromFunction $ \ y0 y1 d t0 ->
cubicHermite (t0,(y0,yd0)) (t0+d,(y1,yd1))
curveMultiscale :: (y -> y -> y) -> y -> y -> Sig.T y
curveMultiscale op d y0 =
Sig.cons y0 (Sig.map (op y0) (Sig.iterateAssociative op d))
curveMultiscaleNeutral :: (y -> y -> y) -> y -> y -> Sig.T y
curveMultiscaleNeutral op d neutral =
Sig.cons neutral (Sig.iterateAssociative op d)