module Synthesizer.Dimensional.Process (
T(..),
run, withParam, getSampleRate,
toTimeScalar, toFrequencyScalar,
toTimeDimension, toFrequencyDimension,
loop, pure,
($:), ($::), ($^), ($#),
(.:), (.^),
liftP, liftP2, liftP3, liftP4,
) where
import qualified Synthesizer.Dimensional.Rate as Rate
import qualified Number.DimensionTerm as DN
import qualified Algebra.DimensionTerm as Dim
import Number.DimensionTerm ((*&), )
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
import Control.Monad.Fix (MonadFix(mfix), )
import Synthesizer.ApplicativeUtility
import qualified Control.Applicative as App
import Control.Applicative (Applicative)
newtype T s u t a = Cons {process :: Rate.T s u t -> a}
instance Functor (T s u t) where
fmap f (Cons g) = Cons (f . g)
instance Applicative (T s u t) where
pure = pure
(<*>) = apply
instance Monad (T s u t) where
return = pure
(>>=) = bind
instance MonadFix (T s u t) where
mfix = loop . withParam
pure :: a -> T s u t a
pure = Cons . const
apply :: T s u t (a -> b) -> T s u t a -> T s u t b
apply (Cons f) arg = Cons $ \sr -> f sr (process arg sr)
run :: (Dim.C u) => DN.T (Dim.Recip u) t -> (forall s. T s u t a) -> a
run sampleRate f = process f (Rate.fromDimensionNumber sampleRate)
bind :: T s u t a -> (a -> T s u t b) -> T s u t b
bind (Cons f) mg =
Cons $ \ sr -> process (mg (f sr)) sr
withParam :: (a -> T s u t b) -> T s u t (a -> b)
withParam f = Cons (\sr a -> process (f a) sr)
getSampleRate :: Dim.C u => T s u t (DN.T (Dim.Recip u) t)
getSampleRate = Cons Rate.toDimensionNumber
toTimeScalar :: (Ring.C t, Dim.C u) =>
DN.T u t -> T s u t t
toTimeScalar time =
fmap (DN.mulToScalar time) getSampleRate
toFrequencyScalar :: (Field.C t, Dim.C u) =>
DN.T (Dim.Recip u) t -> T s u t t
toFrequencyScalar freq =
fmap (DN.divToScalar freq) getSampleRate
toTimeDimension :: (Field.C t, Dim.C u) =>
t -> T s u t (DN.T u t)
toTimeDimension t =
fmap (\sampleRate -> t *& DN.unrecip sampleRate) getSampleRate
toFrequencyDimension :: (Ring.C t, Dim.C u) =>
t -> T s u t (DN.T (Dim.Recip u) t)
toFrequencyDimension f =
fmap (\sampleRate -> f *& sampleRate) getSampleRate