synthesizer-dimensional-0.2: src/Synthesizer/Dimensional/Amplitude/Control.hs
{- |
Copyright : (c) Henning Thielemann 2008
License : GPL
Maintainer : synthesizer@henning-thielemann.de
Stability : provisional
Portability : requires multi-parameter type classes
Control curves which can be used
as envelopes, for controlling filter parameters and so on.
-}
module Synthesizer.Dimensional.Amplitude.Control
({- * Primitives -}
constant, constantVector,
{- * Preparation -}
mapLinear, mapLinearDimension,
mapExponential,
) where
import qualified Synthesizer.Dimensional.Abstraction.RateIndependent as Ind
import qualified Synthesizer.Dimensional.Abstraction.Flat as Flat
-- import qualified Synthesizer.Dimensional.RatePhantom as RP
import qualified Synthesizer.Dimensional.Straight.Signal as SigS
import qualified Synthesizer.Dimensional.Amplitude.Signal as SigA
import Synthesizer.Dimensional.Amplitude.Signal (toAmplitudeScalar)
import qualified Synthesizer.State.Control as Ctrl
import qualified Synthesizer.State.Signal as Sig
import qualified Number.DimensionTerm as DN
import qualified Algebra.DimensionTerm as Dim
import Number.DimensionTerm ((&*&))
-- import qualified Algebra.Module as Module
import qualified Algebra.Transcendental as Trans
import qualified Algebra.Field as Field
import qualified Algebra.Real as Real
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import NumericPrelude
import PreludeBase as P
import Prelude ()
{-# INLINE constant #-}
constant :: (Real.C y, Dim.C u) =>
DN.T u y {-^ value -}
-> SigA.R s u y y
constant =
uncurry constantVector .
DN.absSignum
{- |
The amplitude must be positive!
This is not checked.
-}
{-# INLINE constantVector #-}
constantVector :: -- (Field.C y', Real.C y', OccScalar.C y y') =>
DN.T u y {-^ amplitude -}
-> yv {-^ value -}
-> SigA.R s u y yv
constantVector y yv =
SigA.fromSamples y (Ctrl.constant yv)
{-
This signature is too general.
It will cause strange type errors
if u is Scalar and further process want to use the Flat instance.
The Flat instance cannot be found, if q cannot be determined.
mapLinear :: (Ind.C w, Flat.C flat y, Ring.C y, Dim.C u) =>
y ->
DN.T u q ->
w flat y ->
w (SigA.S u q) y
-}
{-# INLINE mapLinear #-}
mapLinear :: (Ind.C w, Flat.C flat y, Ring.C y, Dim.C u) =>
y ->
DN.T u y ->
w flat y ->
w (SigA.S u y) y
mapLinear depth center =
Ind.processSignal
(SigA.Cons center . SigS.Cons .
Sig.map (\x -> one+x*depth) .
Flat.unwrappedToSamples)
{-# INLINE mapExponential #-}
mapExponential :: (Ind.C w, Flat.C flat y, Trans.C y, Dim.C u) =>
y ->
DN.T u q ->
w flat y ->
w (SigA.S u q) y
mapExponential depth center =
Ind.processSignal
(SigA.Cons center . SigS.Cons .
Sig.map (depth**) .
Flat.unwrappedToSamples)
-- combination of 'raise' and 'amplify' ***
{- |
Map a control curve without amplitude unit
by a linear (affine) function with a unit.
-}
{-# INLINE mapLinearDimension #-}
mapLinearDimension ::
(Ind.C w, Field.C y, Real.C y, Dim.C u, Dim.C v) =>
DN.T v y {- ^ range: one is mapped to @center + range * ampX@ -}
-> DN.T (Dim.Mul v u) y {- ^ center: zero is mapped to @center@ -}
-> w (SigA.S u y) y
-> w (SigA.S (Dim.Mul v u) y) y
mapLinearDimension range center x =
let absRange = DN.abs range &*& SigA.amplitude x
absCenter = DN.abs center
rng = toAmplitudeScalar z absRange
cnt = toAmplitudeScalar z absCenter
z =
Ind.processSignal
(SigA.Cons (absRange + absCenter) . SigS.Cons .
Sig.map (\y -> cnt + rng*y) .
SigA.privateSamples) x
in z
-- SynI.mapScalar 1 (absRange + absCenter) (\y -> cnt + rng*y) x