{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Plain.Filter.Recursive.MovingAverage (
sumsStaticInt,
modulatedFrac,
) where
import qualified Synthesizer.Plain.Signal as Sig
import qualified Synthesizer.Plain.Filter.Recursive.Integration as Integration
import Synthesizer.Plain.Filter.NonRecursive (delay, )
import qualified Algebra.Module as Module
import qualified Algebra.RealField as RealField
import qualified Algebra.Additive as Additive
import Control.Monad.Fix (fix)
import Data.List (tails)
import NumericPrelude.Numeric
import NumericPrelude.Base
sumsStaticInt :: (Additive.C v) => Int -> Sig.T v -> Sig.T v
sumsStaticInt n xs =
fix (\ys -> let (xs0,xs1) = splitAt n xs
in (xs0 ++ (xs1-xs)) + (zero:ys))
_sumFromTo :: (Additive.C v) => Int -> Int -> Sig.T v -> v
_sumFromTo from to =
if from <= to
then sum . take (to-from) . drop from
else negate . sum . take (from-to) . drop to
sumFromToFrac :: (RealField.C a, Module.C a v) => a -> a -> Sig.T v -> v
sumFromToFrac from to xs =
let (fromInt, fromFrac) = splitFraction from
(toInt, toFrac) = splitFraction to
in case compare fromInt toInt of
EQ -> (to-from) *> (xs !! fromInt)
LT ->
sum $
zipWith id
(((1-fromFrac) *>) :
replicate (toInt-fromInt-1) id ++
(toFrac *>) :
[]) $
drop fromInt xs
GT ->
negate $ sum $
zipWith id
(((1-toFrac) *>) :
replicate (fromInt-toInt-1) id ++
(fromFrac *>) :
[]) $
drop toInt xs
sumDiffsModulated :: (RealField.C a, Module.C a v) =>
a -> Sig.T a -> Sig.T v -> Sig.T v
sumDiffsModulated d ds =
zipWith3 sumFromToFrac ((d+1) : ds) (map (1+) ds) .
init . init . tails . (zero:)
_sumsModulated :: (RealField.C a, Module.C a v) =>
Int -> Sig.T a -> Sig.T v -> Sig.T v
_sumsModulated maxDInt ds xs =
let maxD = fromIntegral maxDInt
posXs = sumDiffsModulated 0 ds xs
negXs = sumDiffsModulated maxD (map (maxD-) ds) (delay maxDInt xs)
in Integration.run (posXs - negXs)
sumsModulatedHalf :: (RealField.C a, Module.C a v) =>
Int -> Sig.T a -> Sig.T v -> Sig.T v
sumsModulatedHalf maxDInt ds xs =
let maxD = fromIntegral maxDInt
d0 = maxD+0.5
delXs = delay maxDInt xs
posXs = sumDiffsModulated d0 (map (d0+) ds) delXs
negXs = sumDiffsModulated d0 (map (d0-) ds) delXs
in Integration.run (posXs - negXs)
modulatedFrac :: (RealField.C a, Module.C a v) =>
Int -> Sig.T a -> Sig.T v -> Sig.T v
modulatedFrac maxDInt ds xs =
zipWith (\d y -> recip (2*d) *> y) ds $
sumsModulatedHalf maxDInt ds xs