module Synthesizer.Plain.Filter.Recursive.SecondOrder where
import Synthesizer.Plain.Filter.Recursive (Passband(Lowpass,Highpass))
import qualified Synthesizer.Plain.Signal as Sig
import qualified Synthesizer.Plain.Modifier as Modifier
import qualified Synthesizer.Interpolation.Class as Interpol
import Synthesizer.ApplicativeUtility (liftA4, liftA5, )
import qualified Synthesizer.Causal.Process as Causal
import qualified Algebra.Module as Module
import qualified Algebra.Field as Field
import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive
import Algebra.Module((*>))
import Data.List (zipWith6)
import Control.Monad.Trans.State (State, state, )
import Foreign.Storable (Storable(..))
import qualified Foreign.Storable.Record as Store
import qualified Prelude as P
import PreludeBase
import NumericPrelude
data Parameter a =
Parameter {c0, c1, c2, d1, d2 :: !a}
deriving Show
data Status a =
Status {u1, u2, y1, y2 :: !a}
deriving Show
zeroStatus :: Additive.C a => Status a
zeroStatus =
Status
{u1 = zero, u2 = zero,
y1 = zero, y2 = zero}
instance Interpol.C a v => Interpol.C a (Parameter v) where
scaleAndAccumulate =
Interpol.runMac $
liftA5 Parameter
(Interpol.element c0)
(Interpol.element c1)
(Interpol.element c2)
(Interpol.element d1)
(Interpol.element d2)
instance Storable a => Storable (Parameter a) where
sizeOf = Store.sizeOf storeParameter
alignment = Store.alignment storeParameter
peek = Store.peek storeParameter
poke = Store.poke storeParameter
storeParameter ::
Storable a => Store.Dictionary (Parameter a)
storeParameter =
Store.run $
liftA5 Parameter
(Store.element c0)
(Store.element c1)
(Store.element c2)
(Store.element d1)
(Store.element d2)
instance Storable a => Storable (Status a) where
sizeOf = Store.sizeOf storeStatus
alignment = Store.alignment storeStatus
peek = Store.peek storeStatus
poke = Store.poke storeStatus
storeStatus ::
Storable a => Store.Dictionary (Status a)
storeStatus =
Store.run $
liftA4 Status
(Store.element u1)
(Store.element u2)
(Store.element y1)
(Store.element y2)
adjustPassband :: (Field.C a) =>
Passband -> (a -> Parameter a) -> (a -> Parameter a)
adjustPassband kind comp f =
case kind of
Lowpass -> comp f
Highpass ->
let p = comp (0.5f)
in Parameter (c0 p) ( c1 p) (c2 p) ( d1 p) (d2 p)
step :: (Ring.C a, Module.C a v) =>
Parameter a -> v -> State (Status v) v
step c u0 = state $ \s ->
let y0 =
c0 c *> u0 +
c1 c *> u1 s + d1 c *> y1 s +
c2 c *> u2 s + d2 c *> y2 s
in (y0, Status
{u1 = u0, u2 = u1 s,
y1 = y0, y2 = y1 s})
modifierInit :: (Ring.C a, Module.C a v) =>
Modifier.Initialized (Status v) (Status v) (Parameter a) v v
modifierInit =
Modifier.Initialized id step
modifier :: (Ring.C a, Module.C a v) =>
Modifier.Simple (Status v) (Parameter a) v v
modifier =
Sig.modifierInitialize modifierInit zeroStatus
causal :: (Ring.C a, Module.C a v) =>
Causal.T (Parameter a, v) v
causal =
Causal.fromSimpleModifier modifier
runInit :: (Ring.C a, Module.C a v) =>
Status v -> Sig.T (Parameter a) -> Sig.T v -> Sig.T v
runInit sInit control input =
let u0s = input
u1s = u1 sInit : u0s
u2s = u2 sInit : u1s
y1s = y1 sInit : y0s
y2s = y2 sInit : y1s
y0s = zipWith6
(\c u0_ u1_ u2_ y1_ y2_ ->
c0 c *> u0_ +
c1 c *> u1_ + d1 c *> y1_ +
c2 c *> u2_ + d2 c *> y2_)
control u0s u1s u2s y1s y2s
in y0s
run :: (Ring.C a, Module.C a v) =>
Sig.T (Parameter a) -> Sig.T v -> Sig.T v
run =
runInit zeroStatus