module Synthesizer.Dimensional.Process (
T(..),
run, withParam, getSampleRate,
toTimeScalar, toFrequencyScalar,
toTimeDimension, toFrequencyDimension,
intFromTime, intFromTime98,
DimensionGradient, toGradientScalar,
loop, pure,
($:), ($::), ($^), ($#),
(.:), (.^),
liftP, liftP2, liftP3, liftP4,
) where
import qualified Number.DimensionTerm as DN
import qualified Algebra.DimensionTerm as Dim
import Number.DimensionTerm ((*&), (&/&), )
import qualified Algebra.RealRing as RealRing
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)
import NumericPrelude.Numeric
import NumericPrelude.Base
import qualified Prelude as P
import Prelude (RealFrac)
newtype T s u t a = Cons {process :: DN.T (Dim.Recip 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 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 id
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
type DimensionGradient u v = Dim.Mul (Dim.Recip u) v
toGradientScalar :: (Field.C q, Dim.C u, Dim.C v) =>
DN.T v q -> DN.T (DimensionGradient u v) q -> T s u q q
toGradientScalar amp steepness =
toFrequencyScalar
(DN.rewriteDimension (Dim.identityRight . Dim.applyRightMul Dim.cancelRight . Dim.associateRight) $
steepness &/& amp)
checkedChunkSize ::
String -> Int -> Int
checkedChunkSize funcName cs =
if cs>0
then cs
else error $ funcName ++ ": negative chunkSize"
intFromTime ::
(RealRing.C t, Dim.C u) =>
String ->
DN.T u t ->
T s u t Int
intFromTime funcName t =
fmap (checkedChunkSize funcName . RealRing.ceiling) $ toTimeScalar t
intFromTime98 ::
(Ring.C t, RealFrac t, Dim.C u) =>
String ->
DN.T u t ->
T s u t Int
intFromTime98 funcName t =
fmap (checkedChunkSize funcName . P.ceiling) $ toTimeScalar t