{-| 
    Module      : Vocoder.Window
    Description : Window functions
    Copyright   : (c) Marek Materzok, 2021
    License     : BSD2

This module defines popular window functions for use in the vocoder
framework.
-}
module Vocoder.Window (
    makeWindow,
    boxWindow,
    triangleWindow,
    hammingWindow,
    hannWindow,
    generalizedBlackmanWindow,
    blackmanWindow,
    exactBlackmanWindow,
    lanczosWindow,
    flatTopWindow
    ) where

import Vocoder
import qualified Data.Vector.Storable as V

-- | Creates a window of given length by sampling a function
--   on the interval [0,1].
makeWindow :: (Double -> Double) -> Length -> Window
makeWindow :: (Double -> Double) -> Length -> Window
makeWindow Double -> Double
f Length
n = Length -> (Length -> Double) -> Window
forall a. Storable a => Length -> (Length -> a) -> Vector a
V.generate Length
n ((Length -> Double) -> Window) -> (Length -> Double) -> Window
forall a b. (a -> b) -> a -> b
$ \Length
k -> Double -> Double
f (Length -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Length
k Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Length -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Length
n Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1))

-- | Creates a box window.
boxWindow :: Length -> Window
boxWindow :: Length -> Window
boxWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ Double -> Double -> Double
forall a b. a -> b -> a
const Double
1

-- | Creates a triangular window.
triangleWindow :: Length -> Window
triangleWindow :: Length -> Window
triangleWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Num a => a -> a
abs (Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
0.5))

-- | Creates a Hamming window.
hammingWindow :: Length -> Window
hammingWindow :: Length -> Window
hammingWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> Double
alpha Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
beta Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x)
    where
    alpha :: Double
alpha = Double
25.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
46.0
    beta :: Double
beta = Double
21.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
46.0

-- | Creates a Hann window.
hannWindow :: Length -> Window
hannWindow :: Length -> Window
hannWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x))

-- | Creates a generalized Blackman window for a given alpha value.
generalizedBlackmanWindow :: Double -> Length -> Window
generalizedBlackmanWindow :: Double -> Length -> Window
generalizedBlackmanWindow Double
a = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> let p :: Double
p = Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x in Double
a0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
p Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
p)
    where
    a0 :: Double
a0 = (Double
1 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2
    a1 :: Double
a1 = Double
0.5
    a2 :: Double
a2 = Double
a Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
2

-- | Creates a Blackman window (with alpha=0.16).
blackmanWindow :: Length -> Window
blackmanWindow :: Length -> Window
blackmanWindow = Double -> Length -> Window
generalizedBlackmanWindow Double
0.16

-- | Creates an exact Blackman window.
exactBlackmanWindow :: Length -> Window
exactBlackmanWindow :: Length -> Window
exactBlackmanWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> let p :: Double
p = Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x in Double
a0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos Double
p Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
p)
    where
    a0 :: Double
a0 = Double
7938.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
18608.0
    a1 :: Double
a1 = Double
9240.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
18608.0
    a2 :: Double
a2 = Double
1430.0Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/Double
18608.0

-- | Creates a Lanczos window.
lanczosWindow :: Length -> Window
lanczosWindow :: Length -> Window
lanczosWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> Double -> Double
forall p. (Eq p, Floating p) => p -> p
sinc (Double -> Double) -> Double -> Double
forall a b. (a -> b) -> a -> b
$ Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
1
    where
    sinc :: p -> p
sinc p
0 = p
1
    sinc p
x = p -> p
forall a. Floating a => a -> a
sin (p
forall a. Floating a => a
pip -> p -> p
forall a. Num a => a -> a -> a
*p
x) p -> p -> p
forall a. Fractional a => a -> a -> a
/ (p
forall a. Floating a => a
pip -> p -> p
forall a. Num a => a -> a -> a
*p
x)

-- | Creates a flat top window.
flatTopWindow :: Length -> Window
flatTopWindow :: Length -> Window
flatTopWindow = (Double -> Double) -> Length -> Window
makeWindow ((Double -> Double) -> Length -> Window)
-> (Double -> Double) -> Length -> Window
forall a b. (a -> b) -> a -> b
$ \Double
x -> Double
a0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a1 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a2 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
4 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x) Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
a3 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
6 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x) Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
a4 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double -> Double
forall a. Floating a => a -> a
cos (Double
8 Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
forall a. Floating a => a
pi Double -> Double -> Double
forall a. Num a => a -> a -> a
* Double
x)
    where
    a0 :: Double
a0 = Double
0.21557895
    a1 :: Double
a1 = Double
0.41663158
    a2 :: Double
a2 = Double
0.277263158
    a3 :: Double
a3 = Double
0.083578947
    a4 :: Double
a4 = Double
0.006947368