-- | Windowing functions.
module Sound.SC3.Common.Math.Window where

-- * Type and conversion

-- | A function from a \(0,1)\ normalised input to an output.
type Window x = x -> x

-- | A discrete /n/ element rendering of a 'Window'.
type Table x = [x]

-- | Generate an /n/ element table from a \(0,1)\ normalised window
-- function.
window_table :: (Integral n,Fractional a,Enum a) => n -> Window a -> Table a
window_table :: n -> Window a -> Table a
window_table n
n Window a
f =
    let k :: a
k = a
1 a -> Window a
forall a. Fractional a => a -> a -> a
/ (n -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral n
n a -> Window a
forall a. Num a => a -> a -> a
- a
1)
    in Window a -> Table a -> Table a
forall a b. (a -> b) -> [a] -> [b]
map Window a
f [a
0,a
k..a
1]

-- * Math

-- | /n/ ^ 2.
square :: Num a => a -> a
square :: a -> a
square a
x = a
x a -> a -> a
forall a. Num a => a -> a -> a
* a
x

-- * Window functions

-- | Gaussian window, θ <= 0.5.
gaussian :: Floating a => a -> Window a
gaussian :: a -> Window a
gaussian a
theta a
i = Window a
forall a. Floating a => a -> a
exp (- (a
0.5 a -> Window a
forall a. Num a => a -> a -> a
* Window a
forall a. Num a => a -> a
square ((a
i a -> Window a
forall a. Num a => a -> a -> a
- a
0.5) a -> Window a
forall a. Fractional a => a -> a -> a
/ (a
theta a -> Window a
forall a. Num a => a -> a -> a
* a
0.5))))

-- | Hann raised cosine window.
hann :: Floating a => Window a
hann :: Window a
hann a
i = a
0.5 a -> Window a
forall a. Num a => a -> a -> a
* (a
1 a -> Window a
forall a. Num a => a -> a -> a
- Window a
forall a. Floating a => a -> a
cos (a
2 a -> Window a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi a -> Window a
forall a. Num a => a -> a -> a
* a
i))

-- | Hamming raised cosine window.
hamming :: Floating a => Window a
hamming :: Window a
hamming a
i = a
0.54 a -> Window a
forall a. Num a => a -> a -> a
- a
0.46 a -> Window a
forall a. Num a => a -> a -> a
* Window a
forall a. Floating a => a -> a
cos (a
2 a -> Window a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi a -> Window a
forall a. Num a => a -> a -> a
* a
i)

-- | Unit ('id') window, also known as a Dirichlet window.
rectangular :: Window a
rectangular :: Window a
rectangular = Window a
forall a. a -> a
id

-- | 'sin' window.
sine :: Floating a => Window a
sine :: Window a
sine a
i = Window a
forall a. Floating a => a -> a
sin (a
i a -> Window a
forall a. Num a => a -> a -> a
* a
forall a. Floating a => a
pi)

-- | Triangular window, ie. Bartlett window with zero end-points.
triangular :: Fractional a => Window a
triangular :: Window a
triangular a
i = a
2 a -> Window a
forall a. Num a => a -> a -> a
* (a
0.5 a -> Window a
forall a. Num a => a -> a -> a
- Window a
forall a. Num a => a -> a
abs (a
i a -> Window a
forall a. Num a => a -> a -> a
- a
0.5))

-- * Tables

-- | 'window_table' . 'gaussian'.
--
-- > import Sound.SC3.Plot
-- > plotTable [gaussian_table 1024 0.25,gaussian_table 1024 0.5]
gaussian_table :: (Integral n, Floating b, Enum b) => n -> b -> [b]
gaussian_table :: n -> b -> [b]
gaussian_table n
n = n -> Window b -> [b]
forall n a.
(Integral n, Fractional a, Enum a) =>
n -> Window a -> Table a
window_table n
n (Window b -> [b]) -> (b -> Window b) -> b -> [b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Window b
forall a. Floating a => a -> Window a
gaussian

-- | 'window_table' . 'hamming'.
--
-- > plotTable [hann_table 128,hamming_table 128]
hamming_table :: Int -> [Double]
hamming_table :: Int -> [Double]
hamming_table Int
n = Int -> Window Double -> [Double]
forall n a.
(Integral n, Fractional a, Enum a) =>
n -> Window a -> Table a
window_table Int
n Window Double
forall a. Floating a => a -> a
hamming

-- | 'window_table' . 'hann'.
--
-- > plotTable [hann_table 128]
hann_table :: Int -> [Double]
hann_table :: Int -> [Double]
hann_table Int
n = Int -> Window Double -> [Double]
forall n a.
(Integral n, Fractional a, Enum a) =>
n -> Window a -> Table a
window_table Int
n Window Double
forall a. Floating a => a -> a
hann

-- | 'window_table' . 'sine'.
--
-- plotTable [sine_table 128]
sine_table :: (Integral n, Floating b, Enum b) => n -> [b]
sine_table :: n -> [b]
sine_table n
n = n -> Window b -> [b]
forall n a.
(Integral n, Fractional a, Enum a) =>
n -> Window a -> Table a
window_table n
n Window b
forall a. Floating a => a -> a
sine

-- | 'window_table' . 'triangular'.
--
-- plotTable [triangular_table (2^9)]
triangular_table :: (Integral n, Fractional b, Enum b) => n -> [b]
triangular_table :: n -> [b]
triangular_table n
n = n -> Window b -> [b]
forall n a.
(Integral n, Fractional a, Enum a) =>
n -> Window a -> Table a
window_table n
n Window b
forall a. Fractional a => Window a
triangular