{- | Copyright : (c) Henning Thielemann 2008 License : GPL Maintainer : synthesizer@henning-thielemann.de Stability : provisional Portability : requires multi-parameter type classes Signals equipped with a volume information that may carry a unit. Is the approach with separated volume information still appropriate? Actually it simplifies reusing code from "Synthesizer.State.Signal" because we do not have to replace @(*)@ by @(&*&)@. -} module Synthesizer.Dimensional.Amplitude.Signal where import qualified Synthesizer.Dimensional.Amplitude as Amp import qualified Synthesizer.Format as Format import qualified Synthesizer.Dimensional.Abstraction.RateIndependent as Ind import qualified Synthesizer.Dimensional.RatePhantom as RP import qualified Synthesizer.Dimensional.Straight.Signal as SigS import qualified Synthesizer.State.Filter.NonRecursive as Filt import qualified Synthesizer.State.Signal as Sig import qualified Synthesizer.Generic.Filter.NonRecursive as FiltG import qualified Synthesizer.Generic.Signal as SigG import qualified Number.DimensionTerm as DN import qualified Algebra.DimensionTerm as Dim import qualified Algebra.Module as Module import qualified Algebra.Field as Field import qualified Algebra.Ring as Ring -- import Number.DimensionTerm ((&/&)) import NumericPrelude import PreludeBase as P import Prelude () data T amp sig yv = Cons { privateAmplitude :: amp {-^ scaling of the values -} , signal :: sig yv {-^ the embedded signal -} } -- deriving (Eq, Show) instance (Show amp, Format.C sig) => Format.C (T amp sig) where format p (Cons amp sig) = showParen (p >= 10) (showString "amplitudeSignal " . showsPrec 11 amp . showString " " . Format.format 11 sig) instance (Show amp, Show yv, Format.C sig) => Show (T amp sig yv) where showsPrec = Format.format type R s v y yv = RP.T s (S v y) yv type S v y = D v y SigS.S -- kind * -> * type D v y = T (DN.T v y) {- We removed that instance because 'fmap' is too dangerous for application code. You may write functions that depend on the particular amplitude scaling. instance Dim.C v => Functor (D v y s) where fmap f (Cons amp ss) = Cons amp (map f ss) -} {-# INLINE amplitude #-} amplitude :: (Ind.C w, Dim.C v) => w (D v y sig) yv -> DN.T v y amplitude = privateAmplitude . Ind.toSignal {-# INLINE samples #-} samples :: (Ind.C w, Dim.C v) => w (D v y (SigS.T sig)) yv -> sig yv samples = privateSamples . Ind.toSignal {-# INLINE privateSamples #-} privateSamples :: (Amp.C amp) => T amp (SigS.T sig) yv -> sig yv privateSamples = SigS.samples . signal {-# INLINE phantomSignal #-} phantomSignal :: RP.T s (D v y sig) yv -> RP.T s sig yv phantomSignal = RP.fromSignal . signal . RP.toSignal {-# INLINE toAmplitudeScalar #-} toAmplitudeScalar :: (Ind.C w, Field.C y, Dim.C v) => w (D v y sig) yv -> DN.T v y -> y toAmplitudeScalar sig y = DN.divToScalar y (amplitude sig) {-# INLINE scalarSamples #-} {- scalarSamples :: (Ind.C w, Ring.C y, Dim.C v) => (DN.T v y -> y) -> w (S v y) y -> Sig.T y -} scalarSamples :: (Ind.C w, Ring.C y, Amp.C amp) => (amp -> y) -> w (T amp SigS.S) y -> Sig.T y scalarSamples toAmpScalar = scalarSamplesPrivate toAmpScalar . Ind.toSignal {-# INLINE scalarSamplesGeneric #-} scalarSamplesGeneric :: (Ind.C w, Ring.C y, Dim.C v, SigG.Transform sig y) => (DN.T v y -> y) -> w (D v y (SigS.T sig)) y -> sig y scalarSamplesGeneric toAmpScalar = scalarSamplesPrivateGeneric toAmpScalar . Ind.toSignal {-# INLINE vectorSamples #-} vectorSamples :: (Ind.C w, Module.C y yv, Dim.C v) => (DN.T v y -> y) -> w (S v y) yv -> Sig.T yv vectorSamples toAmpScalar = vectorSamplesPrivate toAmpScalar . Ind.toSignal {-# INLINE rewriteDimension #-} rewriteDimension :: (Dim.C v0, Dim.C v1) => (v0 -> v1) -> D v0 y sig yv -> D v1 y sig yv rewriteDimension f (Cons amp ss) = Cons (DN.rewriteDimension f amp) ss {-# INLINE fromSignal #-} -- fromSignal :: DN.T v y -> SigS.R s yv -> R s v y yv fromSignal :: amp -> SigS.R s yv -> RP.T s (T amp SigS.S) yv fromSignal amp = RP.fromSignal . Cons amp . RP.toSignal {-# INLINE toScalarSignal #-} toScalarSignal :: (Ind.C w, Field.C y, Dim.C v) => DN.T v y -> w (S v y) y -> w SigS.S y toScalarSignal amp = Ind.processSignal (SigS.Cons . scalarSamplesPrivate (flip DN.divToScalar amp)) {-# INLINE toVectorSignal #-} toVectorSignal :: (Ind.C w, Field.C y, Module.C y yv, Dim.C v) => DN.T v y -> w (S v y) yv -> w SigS.S yv toVectorSignal amp = Ind.processSignal (SigS.Cons . vectorSamplesPrivate (flip DN.divToScalar amp)) {-# INLINE scalarSamplesPrivate #-} {- scalarSamplesPrivate :: (Ring.C y, Dim.C v) => (DN.T v y -> y) -> S v y y -> Sig.T y -} scalarSamplesPrivate :: (Ring.C y, Amp.C amp) => (amp -> y) -> T amp SigS.S y -> Sig.T y scalarSamplesPrivate toAmpScalar sig = let y = toAmpScalar (privateAmplitude sig) in Filt.amplify y (privateSamples sig) {-# INLINE scalarSamplesPrivateGeneric #-} scalarSamplesPrivateGeneric :: (Ring.C y, Dim.C v, SigG.Transform sig y) => (DN.T v y -> y) -> D v y (SigS.T sig) y -> sig y scalarSamplesPrivateGeneric toAmpScalar sig = let y = toAmpScalar (privateAmplitude sig) in FiltG.amplify y (privateSamples sig) {-# INLINE vectorSamplesPrivate #-} vectorSamplesPrivate :: (Module.C y yv, Dim.C v) => (DN.T v y -> y) -> S v y yv -> Sig.T yv vectorSamplesPrivate toAmpScalar sig = let y = toAmpScalar (privateAmplitude sig) in y *> privateSamples sig {-# INLINE fromSamples #-} -- fromSamples :: (Dim.C v) => DN.T v y -> Sig.T yv -> R s v y yv fromSamples :: {- (Amp.C amp) => -} amp -> Sig.T yv -> RP.T s (T amp SigS.S) yv fromSamples amp = fromSignal amp . SigS.fromSamples {-# INLINE fromScalarSamples #-} fromScalarSamples :: {- (Amp.C amp) => -} amp -> Sig.T y -> RP.T s (T amp SigS.S) y fromScalarSamples = fromSamples {-# INLINE fromVectorSamples #-} fromVectorSamples :: {- (Amp.C amp) => -} amp -> Sig.T yv -> RP.T s (T amp SigS.S) yv fromVectorSamples = fromSamples {-# INLINE replaceAmplitude #-} replaceAmplitude :: (Ind.C w, Dim.C v0, Dim.C v1) => DN.T v1 y -> w (D v0 y sig) yv -> w (D v1 y sig) yv replaceAmplitude amp = Ind.processSignal (replaceAmplitudePrivate amp) {-# INLINE replaceSamples #-} replaceSamples :: (Ind.C w, Dim.C v) => sig1 yv1 -> w (D v y sig0) yv0 -> w (D v y (SigS.T sig1)) yv1 replaceSamples ss = Ind.processSignal (replaceSamplesPrivate ss) {-# INLINE replaceAmplitudePrivate #-} replaceAmplitudePrivate :: (Dim.C v0, Dim.C v1) => DN.T v1 y -> D v0 y sig yv -> D v1 y sig yv replaceAmplitudePrivate amp = Cons amp . signal {-# INLINE replaceSamplesPrivate #-} replaceSamplesPrivate :: (Dim.C v) => sig1 yv1 -> D v y sig0 yv0 -> D v y (SigS.T sig1) yv1 replaceSamplesPrivate ss x = Cons (privateAmplitude x) (SigS.Cons ss) {-# INLINE processSamples #-} processSamples :: (Ind.C w, Dim.C v) => (sig0 yv0 -> sig1 yv1) -> w (D v y (SigS.T sig0)) yv0 -> w (D v y (SigS.T sig1)) yv1 processSamples f = Ind.processSignal (processSamplesPrivate f) {-# INLINE processSamplesPrivate #-} processSamplesPrivate :: (Dim.C v) => (sig0 yv0 -> sig1 yv1) -> D v y (SigS.T sig0) yv0 -> D v y (SigS.T sig1) yv1 processSamplesPrivate f (Cons amp sig) = Cons amp (SigS.processSamplesPrivate f sig) {-# INLINE asTypeOfAmplitude #-} asTypeOfAmplitude :: y -> w (D v y sig) yv -> y asTypeOfAmplitude = const