packages feed

dsp-0.1: DSP/Filter/FIR/Window.hs

-----------------------------------------------------------------------------
-- |
-- Module      :  DSP.Filter.FIR.Window
-- Copyright   :  (c) Matthew Donadio 1998
-- License     :  GPL
--
-- Maintainer  :  m.p.donadio@ieee.org
-- Stability   :  experimental
-- Portability :  portable
--
-- Commonly used window functions.  Except for the Parzen window, the
-- results of all of these /look/ right, but I have to check them against
-- either Matlab or my C code.
--
-- More windowing functions exist, but I have to dig through my papers to
-- find the equations.
--
-----------------------------------------------------------------------------

-- TODO: These functions should probably be reworked to use list
-- comprehensions...

{-

Reference:

@Book{dsp,
  author = 	 "Alan V. Oppenheim and Ronald W. Schafer",
  title = 	 "Discrete-Time Signal Processing",
  publisher = 	 "Pretice-Hall",
  year = 	 1989,
  address =	 "Englewood Cliffs",
  series =       {Pretice-Hall Signal Processing Series}
}

@Book{kay,
  author =       "Steven M. Kay",
  title =        "Modern Spectral Estimation: Theory \& Application",
  publisher =    "Prentice Hall",
  year =         1988,
  address =      "Englewood Cliffs",
  series =       {Pretice-Hall Signal Processing Series}
}

-}

module DSP.Filter.FIR.Window (window, rectangular, bartlett, hanning, hamming, blackman, 
         kaiser, gen_hamming, parzen) where

import Data.Array

-- | Applys a window, @w@, to a sequence @x@

window :: Array Int Double -- ^ w[n]
       -> Array Int Double -- ^ x[n]
       -> Array Int Double -- ^ w[n] * x[n]

window w x = listArray (0,m) [ w!i * x!i | i <- [0..m] ]
    where m = snd $ bounds w

-- | rectangular window

rectangular :: Int -- ^ M
	    -> Array Int Double -- ^ w[n]

rectangular m = listArray (0,m) $ replicate (m+1) 1.0

-- | Bartlett  window

bartlett :: Int -- ^ M
	 -> Array Int Double -- ^ w[n]

bartlett m = listArray (0,m) $ map (bartlett' md) [ 0.0 .. md ]
    where bartlett' m n | n <= m / 2  = 2 * n / m
                        | otherwise   = 2 - 2 * n / m
	  md = fromIntegral m

-- | Hanning window

hanning :: Int -- ^ M
	-> Array Int Double -- ^ w[n]

hanning m = listArray (0,m) $ map (hanning' md) [ 0.0 .. md ]
    where hanning' m n = 0.5 - 0.5 * cos(2 * pi * n / m)
	  md = fromIntegral m

-- | Hamming window

hamming :: Int -- ^ M
	-> Array Int Double -- ^ w[n]

hamming m = listArray (0,m) $ map (hamming' md) [ 0.0 .. md ]
    where hamming' m n = 0.54 - 0.46 * cos(2 * pi * n / m)
	  md = fromIntegral m

-- | Blackman window

blackman :: Int -- ^ M
	 -> Array Int Double -- ^ w[n]

blackman m = listArray (0,m) $ map (blackman' md) [ 0.0 .. md ]
    where blackman' m n = 0.42 - 0.5 * cos(2 * pi * n / m) + 
			  0.08 * cos (4 * pi * n / m)
	  md = fromIntegral m

-- | Generalized Hamming window

gen_hamming :: Double -- ^ alpha
	    -> Int -- ^ M
	    -> Array Int Double -- ^ w[n]

gen_hamming a m = listArray (0,m) $ map (hamming' a md) [ 0.0 .. md ]
    where hamming' a m n = a - (1 - a) * cos(2 * pi * n / m)
          md = fromIntegral m

-- | rectangular window

kaiser :: Double -- ^ beta
       -> Int -- ^ M
       -> Array Int Double -- ^ w[n]

kaiser b m = listArray (0,m) $ map (kaiser' b md) [ 0.0 .. md ]
    where kaiser' b m n = i0 (b * sqrt (1 -((n-a)/a)^2)) / i0 b
	  md = fromIntegral m
          a = md / 2

-- Recursive computation of I0, the zeroth-order modified Bessel function
-- of the first kind.

i0  :: Double -> Double
i0 x = i0' x 2 1

i0'                      :: Double -> Double -> Double -> Double
i0' x d ds | ds < 1.0e-30 = 1
           | otherwise = ds * x^2 / d^2 + (i0' x (d+2) (ds * x^2 / d^2))

-- I don't think this one is correct.  Kay's book uses different variable
-- conventions and I haven't deciphered them yet...

-- | rectangular window

parzen :: Int -- ^ M
       -> Array Int Double -- ^ w[n]

parzen m = listArray (0,m) $ map (parzen' md) [ 0.0 .. md ]
    where parzen' m n | n <= m / 2  = 2 * (1-n/m) ^ 3 - (1-2*n/m) ^ 3
                      | otherwise   = 2 * (1-n/m) ^ 3
	  md = fromIntegral m