{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Synthesizer.State.Control (
constant,
line,
linear, linearMultiscale, linearMultiscaleNeutral,
exponential, exponentialMultiscale, exponentialMultiscaleNeutral,
exponential2, exponential2Multiscale, exponential2MultiscaleNeutral,
exponentialFromTo, exponentialFromToMultiscale,
vectorExponential,
vectorExponential2,
cosine,
cubicHermite,
curveMultiscale,
curveMultiscaleNeutral,
) where
import qualified Synthesizer.Plain.Control as Ctrl
import qualified Synthesizer.State.Signal as Sig
import qualified Algebra.Module as Module
import qualified Algebra.Transcendental as Trans
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import NumericPrelude.Numeric
import NumericPrelude.Base
{-# INLINE constant #-}
constant :: a -> Sig.T a
constant = Sig.repeat
{-# INLINE linear #-}
linear :: Additive.C a =>
a
-> a
-> Sig.T a
linear d y0 = Sig.iterate (d+) y0
{-# INLINE linearMultiscale #-}
linearMultiscale :: Additive.C y =>
y
-> y
-> Sig.T y
linearMultiscale = curveMultiscale (+)
{-# INLINE linearMultiscaleNeutral #-}
linearMultiscaleNeutral :: Additive.C y =>
y
-> Sig.T y
linearMultiscaleNeutral slope =
curveMultiscaleNeutral (+) slope zero
{-# INLINE line #-}
line :: Field.C y =>
Int
-> (y,y)
-> Sig.T y
line n (y0,y1) =
Sig.take n $ linear ((y1-y0) / fromIntegral n) y0
{-# INLINE exponential #-}
{-# INLINE exponentialMultiscale #-}
exponential, exponentialMultiscale :: Trans.C a =>
a
-> a
-> Sig.T a
exponential time =
Sig.iterate (exp (- recip time) *)
exponentialMultiscale time = curveMultiscale (*) (exp (- recip time))
{-# INLINE exponentialMultiscaleNeutral #-}
exponentialMultiscaleNeutral :: Trans.C y =>
y
-> Sig.T y
exponentialMultiscaleNeutral time =
curveMultiscaleNeutral (*) (exp (- recip time)) one
{-# INLINE exponential2 #-}
{-# INLINE exponential2Multiscale #-}
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)
{-# INLINE exponential2MultiscaleNeutral #-}
exponential2MultiscaleNeutral :: Trans.C y =>
y
-> Sig.T y
exponential2MultiscaleNeutral halfLife =
curveMultiscaleNeutral (*) (0.5 ** recip halfLife) one
{-# INLINE exponentialFromTo #-}
{-# INLINE exponentialFromToMultiscale #-}
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
{-# INLINE vectorExponential #-}
vectorExponential :: (Trans.C a, Module.C a v) =>
a
-> v
-> Sig.T v
vectorExponential time y0 =
Sig.iterate (exp (-1/time) *>) y0
{-# INLINE vectorExponential2 #-}
vectorExponential2 :: (Trans.C a, Module.C a v) =>
a
-> v
-> Sig.T v
vectorExponential2 halfLife y0 =
Sig.iterate (0.5**(1/halfLife) *>) y0
{-# INLINE cosine #-}
cosine :: Trans.C a =>
a
-> a
-> Sig.T a
cosine = Ctrl.cosineWithSlope $
\d x -> Sig.map cos (linear d x)
{-# INLINE cubicHermite #-}
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)
{-# INLINE curveMultiscale #-}
curveMultiscale :: (y -> y -> y) -> y -> y -> Sig.T y
curveMultiscale op d y0 =
Sig.cons y0 (Sig.map (op y0) (Sig.iterateAssociative op d))
{-# INLINE curveMultiscaleNeutral #-}
curveMultiscaleNeutral :: (y -> y -> y) -> y -> y -> Sig.T y
curveMultiscaleNeutral op d neutral =
Sig.cons neutral (Sig.iterateAssociative op d)