module Synthesizer.Interpolation.Class where
import qualified Synthesizer.State.Signal as Sig
import qualified Algebra.Module as Module
import qualified Algebra.PrincipalIdealDomain as PID
import qualified Algebra.Ring as Ring
import qualified Sound.Frame.NumericPrelude.Stereo as Stereo
import qualified Number.Ratio as Ratio
import qualified Number.Complex as Complex
import Control.Applicative (Applicative(pure, (<*>)), liftA2, )
import Data.Tuple.HT (mapPair, mapSnd, fst3, snd3, thd3, )
import NumericPrelude.Numeric hiding (zero, )
import NumericPrelude.Base
import Prelude ()
class Ring.C a => C a v where
scaleAndAccumulate :: (a,v) -> (v, v -> v)
instance C Float Float where
scaleAndAccumulate = scaleAndAccumulateRing
instance C Double Double where
scaleAndAccumulate = scaleAndAccumulateRing
instance (C a v) => C a (Complex.T v) where
scaleAndAccumulate =
makeMac2 (Complex.+:) Complex.real Complex.imag
instance (PID.C a) => C (Ratio.T a) (Ratio.T a) where
scaleAndAccumulate = scaleAndAccumulateRing
instance (C a v, C a w) => C a (v, w) where
scaleAndAccumulate = makeMac2 (,) fst snd
instance (C a v, C a w, C a u) => C a (v, w, u) where
scaleAndAccumulate = makeMac3 (,,) fst3 snd3 thd3
instance C a v => C a (Stereo.T v) where
scaleAndAccumulate =
makeMac2 Stereo.cons Stereo.left Stereo.right
infixl 6 +.*
scale :: C a v => (a,v) -> v
scale = fst . scaleAndAccumulate
scaleAccumulate :: C a v => (a,v) -> v -> v
scaleAccumulate = snd . scaleAndAccumulate
(+.*) :: C a v => v -> (a,v) -> v
(+.*) = flip scaleAccumulate
combine2 :: C a v => a -> (v, v) -> v
combine2 a (x,y) =
scaleAccumulate (onea, x) $
scale (a, y)
combineMany :: C a v => (a, Sig.T a) -> (v, Sig.T v) -> v
combineMany (a,as) (v,vs) =
Sig.foldL (flip scaleAccumulate) (scale (a,v)) $
Sig.zip as vs
scaleAndAccumulateRing ::
Ring.C a =>
(a,a) -> (a, a -> a)
scaleAndAccumulateRing (a,x) =
let ax = a * x
in (ax, (ax+))
scaleAndAccumulateModule ::
Module.C a v =>
(a,v) -> (v, v -> v)
scaleAndAccumulateModule (a,x) =
let ax = a *> x
in (ax, (ax+))
scaleAndAccumulateApplicative ::
(C a v, Applicative f) =>
(a, f v) -> (f v, f v -> f v)
scaleAndAccumulateApplicative (a,x) =
let ax = fmap (curry scaleAndAccumulate a) x
in (fmap fst ax, (fmap snd ax <*>))
scaleAndAccumulateRingApplicative ::
(Ring.C a, Applicative f) =>
(a, f a) -> (f a, f a -> f a)
scaleAndAccumulateRingApplicative (a,x) =
let ax = fmap (a*) x
in (ax, liftA2 (+) ax)
scaleAndAccumulateModuleApplicative ::
(Module.C a v, Applicative f) =>
(a, f v) -> (f v, f v -> f v)
scaleAndAccumulateModuleApplicative (a,x) =
let ax = fmap (a*>) x
in (ax, liftA2 (+) ax)
newtype MAC a v x = MAC {runMac :: (a,v) -> (x, v -> x)}
element ::
(C a x) =>
(v -> x) -> MAC a v x
element f =
MAC $ \(a,x) ->
mapSnd (.f) $ scaleAndAccumulate (a, f x)
instance Functor (MAC a v) where
fmap f (MAC x) =
MAC $ mapPair (f, (f .)) . x
instance Applicative (MAC a v) where
pure x = MAC $ const (x, const x)
MAC f <*> MAC x =
MAC $ \av ->
let (xav,add) = x av
(g,fadd) = f av
in (g xav, \y -> fadd y (add y))
makeMac ::
(C a x) =>
(x -> v) ->
(v -> x) ->
(a,v) -> (v, v -> v)
makeMac cons x =
runMac $ pure cons <*> element x
makeMac2 ::
(C a x, C a y) =>
(x -> y -> v) ->
(v -> x) -> (v -> y) ->
(a,v) -> (v, v -> v)
makeMac2 cons x y =
runMac $ pure cons <*> element x <*> element y
makeMac3 ::
(C a x, C a y, C a z) =>
(x -> y -> z -> v) ->
(v -> x) -> (v -> y) -> (v -> z) ->
(a,v) -> (v, v -> v)
makeMac3 cons x y z =
runMac $ pure cons <*> element x <*> element y <*> element z