{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Plain.Filter.Delay.List (modulated, modulatedRev) where

import qualified Synthesizer.Plain.Interpolation as Interpolation

import Data.List(tails)

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

import NumericPrelude.Numeric
import NumericPrelude.Base


{- |
This function uses suffixes of the reversed signal.
This way small delays perform well
but the big drawback is that the garbage collector
can not deallocate old samples.
-}
modulatedRevCore :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> [a] -> [v] -> [v]
modulatedRevCore :: forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulatedRevCore T a v
ip Int
size [a]
ts [v]
xs =
   forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
      (\a
t [v]
x ->
          let (Int
ti,a
tf) = forall a b. (C a, C b) => a -> (b, a)
splitFraction a
t
          in  forall t y. T t y -> t -> T y -> y
Interpolation.func T a v
ip a
tf (forall a. Int -> [a] -> [a]
drop Int
ti [v]
x))
      [a]
ts (forall a. Int -> [a] -> [a]
drop Int
size (forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl (forall a b c. (a -> b -> c) -> b -> a -> c
flip (:)) [] [v]
xs))

modulatedRev :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> [a] -> [v] -> [v]
modulatedRev :: forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulatedRev T a v
ip Int
maxDelay [a]
ts [v]
xs =
   let size :: Int
size = Int
maxDelay forall a. C a => a -> a -> a
+ forall t y. T t y -> Int
Interpolation.number T a v
ip
   in  forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulatedRevCore T a v
ip
          (Int
size forall a. C a => a -> a -> a
+ Int
1 forall a. C a => a -> a -> a
+ forall t y. T t y -> Int
Interpolation.offset T a v
ip)
          [a]
ts
          (forall a. Int -> a -> [a]
replicate Int
size forall a. C a => a
zero forall a. [a] -> [a] -> [a]
++ [v]
xs)



modulatedCore :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> [a] -> [v] -> [v]
modulatedCore :: forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulatedCore T a v
ip Int
size [a]
ts [v]
xs =
   forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith
      (\a
t [v]
x ->
          let (Int
ti,a
tf) = forall a b. (C a, C b) => a -> (b, a)
splitFraction (-a
t)
          in  forall t y. T t y -> t -> T y -> y
Interpolation.func T a v
ip a
tf (forall a. Int -> [a] -> [a]
drop (Int
sizeforall a. C a => a -> a -> a
+Int
ti) [v]
x))
      [a]
ts (forall a. [a] -> [[a]]
tails [v]
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.
-}
modulated :: (RealField.C a, Additive.C v) =>
   Interpolation.T a v -> Int -> [a] -> [v] -> [v]
modulated :: forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulated T a v
ip Int
maxDelay [a]
ts [v]
xs =
   let size :: Int
size = Int
maxDelay forall a. C a => a -> a -> a
+ forall t y. T t y -> Int
Interpolation.number T a v
ip
   in  forall a v. (C a, C v) => T a v -> Int -> [a] -> [v] -> [v]
modulatedCore T a v
ip
          (Int
size forall a. C a => a -> a -> a
- forall t y. T t y -> Int
Interpolation.offset T a v
ip)
          [a]
ts
          (forall a. Int -> a -> [a]
replicate Int
size forall a. C a => a
zero forall a. [a] -> [a] -> [a]
++ [v]
xs)