{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE UndecidableInstances #-} {- | This is like "Synthesizer.LLVM.CausalParameterized.Controlled" but for vectorised signals. -} module Synthesizer.LLVM.CausalParameterized.ControlledPacked ( C(process), processCtrlRate, ) where import qualified Synthesizer.LLVM.Filter.Allpass as Allpass import qualified Synthesizer.LLVM.Filter.FirstOrder as Filt1 import qualified Synthesizer.LLVM.Filter.SecondOrder as Filt2 import qualified Synthesizer.LLVM.Filter.SecondOrderCascade as Cascade import qualified Synthesizer.LLVM.Filter.Moog as Moog import qualified Synthesizer.LLVM.Filter.Universal as UniFilter import qualified Synthesizer.LLVM.Frame.SerialVector as Serial import qualified Synthesizer.LLVM.CausalParameterized.ProcessPacked as CausalPS import qualified Synthesizer.LLVM.CausalParameterized.Process as CausalP import qualified Synthesizer.LLVM.Parameterized.Signal as SigP import qualified Synthesizer.LLVM.Parameter as Param import qualified LLVM.Extra.Memory as Memory import qualified LLVM.Extra.ScalarOrVector as SoV import qualified LLVM.Extra.Class as Class import qualified LLVM.Extra.Arithmetic as A import LLVM.Extra.Class (MakeValueTuple, ValueTuple, ) import qualified LLVM.Core as LLVM import LLVM.Util.Loop (Phi, ) import LLVM.Core (Value, IsFloating, IsSized, ) import qualified Types.Data.Num as TypeNum import Types.Data.Num.Ops ((:*:), ) import Foreign.Storable (Storable, ) import Control.Arrow ((<<<), arr, first, ) import qualified Algebra.Field as Field import NumericPrelude.Numeric import NumericPrelude.Base {- | A filter parameter type uniquely selects a filter function. However it does not uniquely determine the input and output type, since the same filter can run on mono and stereo signals. -} class (a ~ Input parameter b, b ~ Output parameter a) => C parameter a b where type Input parameter b :: * type Output parameter a :: * process :: CausalP.T p (parameter, a) b processCtrlRate :: (C parameter av bv, Serial.Read av, n ~ Serial.Size av, a ~ Serial.Element av, Serial.C bv, n ~ Serial.Size bv, b ~ Serial.Element bv, Memory.C parameter, Field.C r, Storable r, IsFloating r, SoV.IntegerConstant r, Memory.FirstClass r, Memory.Stored r ~ rm, IsSized r, IsSized rm, MakeValueTuple r, ValueTuple r ~ (Value r), LLVM.CmpRet r, LLVM.CmpResult r ~ Bool) => Param.T p r -> (Param.T p r -> SigP.T p parameter) -> CausalP.T p av bv processCtrlRate reduct ctrlGen = Serial.withSize $ \n -> CausalP.applyFst process (SigP.interpolateConstant (fmap (/ fromIntegral n) reduct) (ctrlGen reduct)) {- Instances for the particular filters shall be defined here in order to avoid orphan instances. -} instance (Serial.C v, Serial.Element v ~ a, A.PseudoRing a, A.IntegerConstant a, Memory.C a, A.PseudoRing v) => C (Filt1.Parameter a) v (Filt1.Result v) where type Input (Filt1.Parameter a) (Filt1.Result v) = v type Output (Filt1.Parameter a) v = Filt1.Result v process = Filt1.causalPacked instance (Serial.C v, Serial.Element v ~ a, A.PseudoRing a, A.IntegerConstant a, Memory.C a, A.PseudoRing v, A.IntegerConstant v, Memory.C v) => C (Filt2.Parameter a) v v where type Input (Filt2.Parameter a) v = v type Output (Filt2.Parameter a) v = v process = Filt2.causalPacked instance (LLVM.Value a ~ A.Scalar v, A.PseudoModule v, Serial.C v, Serial.Element v ~ LLVM.Value a, SoV.IntegerConstant a, A.PseudoRing v, A.IntegerConstant v, Memory.C v, Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am, LLVM.IsPrimitive a, LLVM.IsPrimitive am, TypeNum.PositiveT (n :*: LLVM.UnknownSize), TypeNum.NaturalT n) => C (Cascade.ParameterValue n a) v v where type Input (Cascade.ParameterValue n a) v = v type Output (Cascade.ParameterValue n a) v = v process = Cascade.causalPacked instance (Serial.C v, Serial.Element v ~ a, Memory.C a, A.IntegerConstant a, A.PseudoRing v, A.PseudoRing a) => C (Allpass.Parameter a) v v where type Input (Allpass.Parameter a) v = v type Output (Allpass.Parameter a) v = v process = Allpass.causalPacked instance (TypeNum.NaturalT n, Serial.C v, Serial.Element v ~ a, A.PseudoRing a, A.IntegerConstant a, Memory.C a, A.PseudoRing v, A.RationalConstant v) => C (Allpass.CascadeParameter n a) v v where type Input (Allpass.CascadeParameter n a) v = v type Output (Allpass.CascadeParameter n a) v = v process = Allpass.cascadePacked instance (Serial.C v, Serial.Element v ~ b, Phi a, Class.Undefined a, a ~ A.Scalar b, A.PseudoModule b, A.IntegerConstant a, Memory.C b, TypeNum.NaturalT n) => C (Moog.Parameter n a) v v where type Input (Moog.Parameter n a) v = v type Output (Moog.Parameter n a) v = v process = CausalPS.pack Moog.causal <<< first (arr Serial.constant) instance (Serial.C v, Serial.Element v ~ b, Phi a, Class.Undefined a, a ~ A.Scalar b, A.PseudoModule b, A.IntegerConstant a, Memory.C b) => C (UniFilter.Parameter a) v (UniFilter.Result v) where type Input (UniFilter.Parameter a) (UniFilter.Result v) = v type Output (UniFilter.Parameter a) v = UniFilter.Result v process = CausalPS.pack UniFilter.causal <<< first (arr Serial.constant)