{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.State.Filter.Delay (
   static,
   staticPad,
   staticPos,
   staticNeg,
   modulated,
   ) where

import qualified Synthesizer.Interpolation as Interpolation
import qualified Synthesizer.State.Interpolation as InterpolationS
import qualified Synthesizer.State.Signal as Sig

import qualified Algebra.RealField as RealField
import qualified Algebra.Additive  as Additive

import NumericPrelude.Numeric



{- * Shift -}

{-# INLINE static #-}
static :: Additive.C y => Int -> Sig.T y -> Sig.T y
static :: forall y. C y => Int -> T y -> T y
static = y -> Int -> T y -> T y
forall y. y -> Int -> T y -> T y
staticPad y
forall a. C a => a
zero

{-# INLINE staticPad #-}
staticPad :: y -> Int -> Sig.T y -> Sig.T y
staticPad :: forall y. y -> Int -> T y -> T y
staticPad = y -> Int -> T y -> T y
forall y. y -> Int -> T y -> T y
InterpolationS.delayPad

{-# INLINE staticPos #-}
staticPos :: Additive.C y => Int -> Sig.T y -> Sig.T y
staticPos :: forall y. C y => Int -> T y -> T y
staticPos Int
n = T y -> T y -> T y
forall a. T a -> T a -> T a
Sig.append (Int -> y -> T y
forall a. Int -> a -> T a
Sig.replicate Int
n y
forall a. C a => a
zero)

{-# INLINE staticNeg #-}
staticNeg :: Int -> Sig.T y -> Sig.T y
staticNeg :: forall y. Int -> T y -> T y
staticNeg = Int -> T y -> T y
forall y. Int -> T y -> T y
Sig.drop



{-# INLINE modulatedCore #-}
modulatedCore :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> Sig.T a -> Sig.T v -> Sig.T v
modulatedCore :: forall a v. (C a, C v) => T a v -> Int -> T a -> T v -> T v
modulatedCore T a v
ip Int
size =
   (a -> T v -> v) -> T a -> T v -> T v
forall y0 y1 y2. (y0 -> T y1 -> y2) -> T y0 -> T y1 -> T y2
Sig.zipWithTails
      (\a
t -> T a v -> a -> T v -> v
forall t y. C t => T t y -> t -> T y -> y
InterpolationS.single T a v
ip (Int -> a
forall a b. (C a, C b) => a -> b
fromIntegral Int
size a -> a -> a
forall a. C a => a -> a -> a
+ a
t))

{-
modulatedCoreSlow :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> Sig.T a -> Sig.T v -> Sig.T v
modulatedCoreSlow ip size ts xs =
   Sig.fromList $ zipWith
      (\t -> Interpolation.single ip (fromIntegral size - t))
      (Sig.toList ts) (Sig.tails xs)
-}

{- |
This is essentially different for constant interpolation,
because this function "looks forward"
whereas the other two variants "look backward".
For the symmetric interpolation functions
of linear and cubic interpolation, this does not really matter.
-}
{-# INLINE modulated #-}
modulated :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> Sig.T a -> Sig.T v -> Sig.T v
modulated :: forall a v. (C a, C v) => T a v -> Int -> T a -> T v -> T v
modulated T a v
ip Int
minDev T a
ts T v
xs =
   let size :: Int
size = T a v -> Int
forall t y. T t y -> Int
Interpolation.number T a v
ip Int -> Int -> Int
forall a. C a => a -> a -> a
- Int
minDev
   in  T a v -> Int -> T a -> T v -> T v
forall a v. (C a, C v) => T a v -> Int -> T a -> T v -> T v
modulatedCore T a v
ip
          (Int
size Int -> Int -> Int
forall a. C a => a -> a -> a
- T a v -> Int
forall t y. T t y -> Int
Interpolation.offset T a v
ip)
          T a
ts
          (Int -> T v -> T v
forall y. C y => Int -> T y -> T y
staticPos Int
size T v
xs)