{-# LANGUAGE NoImplicitPrelude #-}
module Synthesizer.Basic.Filter.NonRecursive where

import qualified Data.List.Match as Match
import Data.Tuple.HT (sortPair, )

import qualified Algebra.Transcendental as Trans
import qualified Algebra.Additive       as Additive

import NumericPrelude.Numeric
import NumericPrelude.Base


unitSizesFromPyramid :: [signal] -> [Int]
unitSizesFromPyramid :: forall signal. [signal] -> [Int]
unitSizesFromPyramid [signal]
pyr =
   [Int] -> [Int]
forall a. [a] -> [a]
reverse ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ [signal] -> [Int] -> [Int]
forall b a. [b] -> [a] -> [a]
Match.take [signal]
pyr ([Int] -> [Int]) -> [Int] -> [Int]
forall a b. (a -> b) -> a -> b
$ (Int -> Int) -> Int -> [Int]
forall a. (a -> a) -> a -> [a]
iterate (Int
2Int -> Int -> Int
forall a. C a => a -> a -> a
*) Int
1

sumRangePrepare :: (Additive.C v) =>
   ((Int,Int) -> source -> v) ->
   (source -> (Int,Int) -> v)
sumRangePrepare :: forall v source.
C v =>
((Int, Int) -> source -> v) -> source -> (Int, Int) -> v
sumRangePrepare (Int, Int) -> source -> v
f source
pyr (Int
l,Int
r) =
   case Int -> Int -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Int
l Int
r of
      Ordering
LT -> (Int, Int) -> source -> v
f (Int
l,Int
r) source
pyr
      Ordering
GT -> v -> v
forall a. C a => a -> a
negate (v -> v) -> v -> v
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> source -> v
f (Int
r,Int
l) source
pyr
      Ordering
EQ -> v
forall a. C a => a
zero

symmetricRangePrepare ::
   ((Int,Int) -> source -> v) ->
   (source -> (Int,Int) -> v)
symmetricRangePrepare :: forall source v.
((Int, Int) -> source -> v) -> source -> (Int, Int) -> v
symmetricRangePrepare (Int, Int) -> source -> v
f source
pyr (Int, Int)
lr = (Int, Int) -> source -> v
f ((Int, Int) -> (Int, Int)
forall a. Ord a => (a, a) -> (a, a)
sortPair (Int, Int)
lr) source
pyr

{-
exp (-(t/var)^2/2) / area *> cis (2*pi*f*t)
  == exp (-(t/var)^2/2 +: 2*pi*f*t) / area
  == exp ((-t^2 +: 2*var^2*2*pi*f*t) / (2*var^2)) / area
  == exp ((t^2 - i*2*var^2*2*pi*f*t) / (-2*var^2)) / area
  == exp (((t^2 - i*var^2*2*pi*f)^2 + (var^2*2*pi*f)^2) / (-2*var^2)) / area
  == exp (((t^2 - i*var^2*2*pi*f)^2 / (-2*var^2) - (var*2*pi*f)^2/2)) / area

sumMap (\t -> exp (-(t/var)^2/2) / area *> cis (2*pi*f*t))
       [-infinity..infinity]
  ~ sumMap (\t -> exp (-(t/var)^2/2)) [-infinity..infinity]
       * exp (-(var*2*pi*f)^2/2) / area
  = exp (-(var*2*pi*f)^2/2)
-}
{- |
  Compute the variance of the Gaussian
  such that its Fourier transform has value @ratio@ at frequency @freq@.
-}
ratioFreqToVariance :: (Trans.C a) => a -> a -> a
ratioFreqToVariance :: forall a. C a => a -> a -> a
ratioFreqToVariance a
ratio a
freq =
   a -> a
forall a. C a => a -> a
sqrt (-a
2 a -> a -> a
forall a. C a => a -> a -> a
* a -> a
forall a. C a => a -> a
log a
ratio) a -> a -> a
forall a. C a => a -> a -> a
/ (a
2a -> a -> a
forall a. C a => a -> a -> a
*a
forall a. C a => a
pia -> a -> a
forall a. C a => a -> a -> a
*a
freq)
           -- inverse of the fourier transformed gaussian