packages feed

synthesizer-llvm-0.5: src/Synthesizer/LLVM/CausalParameterized/ControlledPacked.hs

{-# 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, IsConst, 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 qualified Algebra.Module as Module
-- import qualified Algebra.Ring as Ring
import qualified Algebra.Additive as Additive

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,
    Memory.FirstClass r, Memory.Stored r ~ rm, IsSized r, IsSized rm, IsConst r,
    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 = withSize $ \n ->
   CausalP.applyFst process
      (SigP.interpolateConstant
         (fmap (/ fromInteger (TypeNum.fromIntegerT n)) reduct)
         (ctrlGen reduct))

withSize ::
   (Serial.Read av, n ~ Serial.Size av,
    Serial.Read bv, n ~ Serial.Size bv) =>
   (n -> CausalP.T p av bv) ->
   CausalP.T p av bv
withSize f = f undefined


{-
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.causalPackedP

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.causalPackedP

instance
   (A.PseudoModule (LLVM.Value a) 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.causalPackedP


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.causalPackedP

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.cascadePackedP


instance
   (SoV.PseudoModule a a, SoV.IntegerConstant a, Additive.C a,
    Memory.FirstClass a, Memory.Stored a ~ am, IsSized a, IsSized am,
    MakeValueTuple a, ValueTuple a ~ (Value a), Storable a,
    TypeNum.PositiveT d, LLVM.IsPrimitive a,
    TypeNum.NaturalT n) =>
      C (Moog.Parameter n (Value a))
        (Serial.Value d a) (Serial.Value d a) where
   type Input  (Moog.Parameter n (Value a)) (Serial.Value d a) = (Serial.Value d a)
   type Output (Moog.Parameter n (Value a)) (Serial.Value d a) = (Serial.Value d a)
   process =
      CausalPS.pack Moog.causalP <<<
      first (arr Serial.constant)


instance
   (Serial.C v, Serial.Element v ~ b, Phi a, Class.Undefined a,
    A.PseudoModule a 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.causalP <<<
      first (arr Serial.constant)