{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
module Synthesizer.Plain.Filter.Recursive.FirstOrderComplex (
Parameter,
parameter,
parameterFromPeakWidth,
parameterFromPeakToDCRatio,
step,
modifierInit,
modifier,
causal,
runInit,
run,
) where
import Synthesizer.Plain.Filter.Recursive (Pole(..))
import qualified Synthesizer.Plain.Signal as Sig
import qualified Synthesizer.Plain.Modifier as Modifier
import qualified Synthesizer.Causal.Process as Causal
import qualified Synthesizer.Interpolation.Class as Interpol
import qualified Synthesizer.Basic.ComplexModule as CM
import qualified Number.Complex as Complex
import qualified Algebra.Module as Module
import qualified Algebra.Transcendental as Trans
import qualified Algebra.Algebraic as Algebraic
import qualified Algebra.Ring as Ring
import Control.Monad.Trans.State (State, state, )
import NumericPrelude.Numeric
import NumericPrelude.Base
data Parameter a =
Parameter {c, amp :: !(Complex.T a)}
deriving Show
instance Interpol.C a v => Interpol.C a (Parameter v) where
{-# INLINE scaleAndAccumulate #-}
scaleAndAccumulate = Interpol.makeMac2 Parameter c amp
{-# INLINE parameter #-}
parameter :: Trans.C a => Pole a -> Parameter a
parameter (Pole resonance frequency) =
let cisw = Complex.cis (2*pi*frequency)
k = 1 - recip resonance
kcisw = Complex.scale k cisw
in Parameter kcisw one
{-# INLINE parameterFromPeakWidth #-}
parameterFromPeakWidth :: Trans.C a => a -> Pole a -> Parameter a
parameterFromPeakWidth width (Pole resonance frequency) =
let cisw = Complex.cis (2*pi*frequency)
k = solveRatio resonance (cos (2*pi*width))
kcisw = Complex.scale k cisw
amp_ = Complex.fromReal ((1-k)*resonance)
in Parameter kcisw amp_
{-# INLINE parameterFromPeakToDCRatio #-}
parameterFromPeakToDCRatio :: Trans.C a => Pole a -> Parameter a
parameterFromPeakToDCRatio (Pole resonance frequency) =
let cisw = Complex.cis (2*pi*frequency)
k = solveRatio resonance (Complex.real cisw)
kcisw = Complex.scale k cisw
amp_ = one - kcisw
in Parameter kcisw amp_
solveRatio :: (Algebraic.C a) =>
a -> a -> a
solveRatio resonance cosine =
let r2 = resonance^2
p = (r2 - cosine) / (r2 - 1)
in recip $ p + sqrt (p^2 - 1)
type Result = Complex.T
{-# INLINE step #-}
step :: (Module.C a v) =>
Parameter a -> v -> State (Complex.T v) (Result v)
step p u =
state $ \s ->
let y = CM.scale (amp p) u + CM.mul (c p) s
in (y, y)
{-# INLINE modifierInit #-}
modifierInit :: (Ring.C a, Module.C a v) =>
Modifier.Initialized (Complex.T v) (Complex.T v) (Parameter a) v (Result v)
modifierInit =
Modifier.Initialized id step
{-# INLINE modifier #-}
modifier :: (Ring.C a, Module.C a v) =>
Modifier.Simple (Complex.T v) (Parameter a) v (Result v)
modifier = Sig.modifierInitialize modifierInit zero
{-# INLINE causal #-}
causal ::
(Ring.C a, Module.C a v) =>
Causal.T (Parameter a, v) (Result v)
causal =
Causal.fromSimpleModifier modifier
{-# INLINE runInit #-}
runInit :: (Ring.C a, Module.C a v) =>
Complex.T v -> Sig.T (Parameter a) -> Sig.T v -> Sig.T (Result v)
runInit = Sig.modifyModulatedInit modifierInit
{-# INLINE run #-}
run :: (Ring.C a, Module.C a v) =>
Sig.T (Parameter a) -> Sig.T v -> Sig.T (Result v)
run = runInit zero